New function count_tracks() (Closes: #1144).
[ahxm.git] / song.c
blob0453cd4d3b3afdbd611fe2f74a6d720c06904c5f
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2007 Angel Ortega <angel@triptico.com>
6 song.c - Device-independent song event stream management
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
33 #include "ahxm.h"
35 /*******************
36 Data
37 ********************/
39 /* the song event stream */
40 struct song_ev *song = NULL;
42 /* number of song events */
43 int n_song_ev = 0;
45 /* number of tracks in song */
46 int n_song_tracks = 0;
48 /*******************
49 Code
50 ********************/
52 /**
53 * add_event - Adds an event to an event list.
54 * @song: A pointer to an event list (dynamically allocated)
55 * @count: A pointer to an integer (number of elements)
57 * Increments the @song event list to fit @count number of
58 * elements, probably reallocating its memory.
60 * Returns a pointer to the new element.
62 struct song_ev * add_event(struct song_ev **song, int *count)
64 struct song_ev * r;
66 GROW(*song, *count, struct song_ev);
68 r = *song + *count;
69 memset(r, '\0', sizeof(struct song_ev));
71 (*count)++;
73 return r;
77 /**
78 * copy_event - Appends an event to an event list.
79 * @song: the event list
80 * @count: a pointer to the number of elements
81 * @e: the event to be copied
83 * Appends the @e event to the @song event list.
85 struct song_ev * copy_event(struct song_ev **song, int *count, struct song_ev *e)
87 struct song_ev * r = add_event(song, count);
89 memcpy(r, e, sizeof(struct song_ev));
91 return r;
95 /**
96 * song_clear - Clears the song stream
98 * Clears the song stream.
100 void song_clear(void)
102 if (song != NULL) {
103 free(song);
104 song = NULL;
107 n_song_ev = 0;
111 static void song_trace_events(void)
113 struct song_ev *e;
114 int n;
116 printf("** GENERIC SONG EVENT DUMP **\n\n");
117 printf("%9s %5s %5s Event and information\n", "Time", "Track", "Ev.ID");
118 printf("---------------------------------------------------------------\n");
120 for (n = 0, e = song; n < n_song_ev; n++, e++) {
121 printf("%9.4lf %5d %5d ",
122 e->time, e->trk_id, e->event_id);
124 switch (e->type) {
125 case SONG_EV_TEMPO:
127 printf("SONG_EV_TEMPO ");
128 printf("TEMPO:%lf", e->amount);
129 break;
131 case SONG_EV_METER:
133 printf("SONG_EV_METER ");
134 printf("METER:%d/%d", e->min, e->max);
135 break;
137 case SONG_EV_MEASURE:
139 printf("SONG_EV_MEASURE ");
140 printf("LINE:%d", e->value);
141 break;
143 case SONG_EV_SS_SUSTAIN:
145 printf("SONG_EV_SS_SUSTAIN ");
146 printf("SUSTAIN:%lf", e->amount);
147 break;
149 case SONG_EV_SS_VIBRATO:
151 printf("SONG_EV_SS_VIBRATO ");
152 printf("DEPTH:%lf FREQ:%lf", e->depth, e->freq);
153 break;
155 case SONG_EV_SS_PORTAMENTO:
157 printf("SONG_EV_SS_PORTAMENTO ");
158 printf("VALUE: %lf", e->amount);
159 break;
161 case SONG_EV_SS_CHANNEL:
163 printf("SONG_EV_SS_CHANNEL ");
164 printf("CHANNEL:%d VOL:%lf", e->channel, e->vol);
165 break;
167 case SONG_EV_SS_WAV:
169 printf("SONG_EV_SS_WAV ");
170 printf("FILE:'%s' BASE:%d MIN:%d MAX:%d START:%lf END:%lf",
171 e->name, e->value,
172 e->min, e->max,
173 e->start, e->end);
174 break;
176 case SONG_EV_SS_PAT:
178 printf("SONG_EV_SS_PAT ");
179 printf("FILE:'%s'", e->name);
180 break;
182 case SONG_EV_SS_EFF_DELAY:
184 printf("SONG_EV_SS_EFF_DELAY ");
185 printf("CHANNEL:%d ", e->channel);
186 printf("SIZE:%lf ", e->len);
187 break;
189 case SONG_EV_SS_EFF_ECHO:
191 printf("SONG_EV_SS_EFF_ECHO ");
192 printf("CHANNEL:%d ", e->channel);
193 printf("SIZE:%lf ", e->len);
194 printf("GAIN:%f ", e->vol);
195 break;
197 case SONG_EV_SS_EFF_COMB:
199 printf("SONG_EV_SS_EFF_COMB ");
200 printf("CHANNEL:%d ", e->channel);
201 printf("SIZE:%lf ", e->len);
202 printf("GAIN:%f ", e->vol);
203 break;
205 case SONG_EV_SS_EFF_ALLPASS:
207 printf("SONG_EV_SS_EFF_ALLPASS ");
208 printf("CHANNEL:%d ", e->channel);
209 printf("SIZE:%lf ", e->len);
210 printf("GAIN:%f ", e->vol);
211 break;
213 case SONG_EV_SS_EFF_FLANGER:
215 printf("SONG_EV_SS_EFF_FLANGER ");
216 printf("CHANNEL:%d ", e->channel);
217 printf("SIZE:%lf ", e->len);
218 printf("GAIN:%f ", e->vol);
219 printf("DEPTH:%lf ", e->depth);
220 printf("FREQ:%lf PHASE:%lf", e->freq, e->phase);
221 break;
223 case SONG_EV_SS_EFF_WOBBLE:
225 printf("SONG_EV_SS_EFF_WOBBLE ");
226 printf("CHANNEL:%d ", e->channel);
227 printf("FREQ:%lf PHASE:%lf GAIN:%lf", e->freq,
228 e->phase, e->vol);
229 break;
231 case SONG_EV_SS_EFF_SQWOBBLE:
233 printf("SONG_EV_SS_EFF_SQWOBBLE ");
234 printf("CHANNEL:%d ", e->channel);
235 printf("FREQ:%lf PHASE:%lf", e->freq, e->phase);
236 break;
238 case SONG_EV_SS_EFF_HFWOBBLE:
240 printf("SONG_EV_SS_EFF_HFWOBBLE ");
241 printf("CHANNEL:%d ", e->channel);
242 printf("FREQ:%lf PHASE:%lf", e->freq, e->phase);
243 break;
245 case SONG_EV_SS_EFF_FADER:
247 printf("SONG_EV_SS_EFF_FADER ");
248 printf("CHANNEL:%d ", e->channel);
249 printf("SIZE:%lf ", e->len);
250 printf("INITIAL:%f FINAL:%f", e->initial, e->final);
251 break;
253 case SONG_EV_SS_EFF_REVERB:
255 printf("SONG_EV_SS_EFF_REVERB ");
256 printf("CHANNEL:%d ", e->channel);
257 break;
259 case SONG_EV_SS_EFF_FOLDBACK:
261 printf("SONG_EV_SS_EFF_FOLDBACK ");
262 printf("CHANNEL:%d THRESHOLD:%f", e->channel, e->vol);
263 break;
265 case SONG_EV_SS_EFF_ATAN:
267 printf("SONG_EV_SS_EFF_ATAN ");
268 printf("CHANNEL:%d GAIN:%f", e->channel, e->vol);
269 break;
271 case SONG_EV_SS_EFF_DISTORT:
273 printf("SONG_EV_SS_EFF_DISTORT ");
274 printf("CHANNEL:%d GAIN:%f", e->channel, e->vol);
275 break;
277 case SONG_EV_SS_EFF_OVERDRIVE:
279 printf("SONG_EV_SS_EFF_OVERDRIVE ");
280 printf("CHANNEL:%d GAIN:%f", e->channel, e->vol);
281 break;
283 case SONG_EV_SS_EFF_OFF:
285 printf("SONG_EV_SS_EFF_OFF ");
286 printf("CHANNEL:%d ", e->channel);
287 break;
289 case SONG_EV_MIDI_CHANNEL:
291 printf("SONG_EV_MIDI_CHANNEL ");
292 printf("CHANNEL:%d ", e->channel);
293 break;
295 case SONG_EV_MIDI_PROGRAM:
297 printf("SONG_EV_MIDI_PROGRAM ");
298 printf("PROGRAM:%d ", e->value);
299 break;
301 case SONG_EV_BACK:
303 printf("SONG_EV_BACK ");
304 printf("LEN:%lf", e->len);
305 break;
307 case SONG_EV_NOTE:
309 printf("SONG_EV_NOTE ");
310 printf("MIDI:%d LEN:%lf VOL:%f", e->value, e->len, e->vol);
311 break;
313 case SONG_EV_SS_PITCH_STRETCH:
315 printf("SONG_EV_SS_PITCH_STRETCH ");
316 printf("MIDI:%d LEN:%lf VOL:%f", e->value, e->len, e->vol);
317 break;
319 case SONG_EV_SS_PRINT_WAVE_TEMPO:
321 printf("SONG_EV_SS_PRINT_WAVE_TEMPO ");
322 printf("MIDI:%d LEN:%lf", e->value, e->len);
323 break;
325 case SONG_EV_SONG_INFO:
327 printf("SONG_EV_SONG_INFO ");
328 printf("AUTHOR:'%s' NAME:'%s'", e->author, e->name);
329 break;
331 case SONG_EV_EOT:
333 printf("SONG_EV_EOT ");
334 break;
336 default:
337 printf("** Unexpected event type: %d", e->type);
340 printf("\n");
343 printf("\n");
347 static int time_type_eventid_cmp(const void *v1, const void *v2)
348 /* sorts events by time, then type, then event_id */
350 struct song_ev *e1;
351 struct song_ev *e2;
352 int ret;
354 e1 = (struct song_ev *) v1;
355 e2 = (struct song_ev *) v2;
357 ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0));
359 /* same time? order by type of event */
360 if (ret == 0)
361 ret = e1->type - e2->type;
363 /* same time and same event? order by event id */
364 if (ret == 0)
365 ret = e1->event_id - e2->event_id;
367 return ret;
371 static void count_tracks(void)
372 /* sets n_song_tracks */
374 int n;
376 n_song_tracks = 0;
378 for(n = 0; n < n_song_ev; n++) {
379 struct song_ev *e;
381 e = &song[n];
383 if (n_song_tracks < e->trk_id + 1)
384 n_song_tracks = e->trk_id + 1;
389 static void add_eot_events(void)
390 /* travels all events and adds EOT ones */
392 int n, m;
394 for (n = 0; n < n_song_tracks; n++) {
395 struct song_ev *e;
396 double t = -1;
398 for (m = 0; m < n_song_ev; m++) {
399 e = &song[m];
401 /* if this is the track we're looking for
402 and this event time is bigger, store it */
403 if (e->trk_id == n && e->time > t)
404 t = e->time;
407 /* now t has the biggest time; add an EOT event with t */
408 e = add_event(&song, &n_song_ev);
410 e->type = SONG_EV_EOT;
411 e->time = t;
412 e->trk_id = n;
418 * song_sort - Sorts the song stream
420 * Sorts the song stream.
422 void song_sort(void)
424 count_tracks();
425 add_eot_events();
427 /* sorts by time, type and event_id */
428 qsort(song, n_song_ev, sizeof(struct song_ev), time_type_eventid_cmp);
430 if (trace)
431 song_trace_events();
436 * song_test_measure_boundary - Does a measure boundary check
437 * @ev_time: event time
438 * @num: meter numerator
439 * @den: meter denominator
441 * Does a measure boundary check. Returns 0 if the event time falls
442 * exactly between two measures, or nonzero otherwise.
444 int song_test_measure_boundary(double ev_time, int num, int den, int line)
446 int ret;
448 if ((ret = ((int) (ev_time * (double) den)) % num))
449 printf("Measure boundary check failed in line %d\n", line);
451 return ret;