Updated TODO.
[ahxm.git] / song.c
blob86704dca3630374e45c8835e7bbe02a8d3c5d9e0
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 case SONG_EV_NOP:
338 printf("SONG_EV_NOP ");
339 break;
341 default:
342 printf("** Unexpected event type: %d", e->type);
345 printf("\n");
348 printf("\n");
352 static int time_type_eventid_cmp(const void *v1, const void *v2)
353 /* sorts events by time, then type, then event_id */
355 struct song_ev *e1;
356 struct song_ev *e2;
357 int ret;
359 e1 = (struct song_ev *) v1;
360 e2 = (struct song_ev *) v2;
362 ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0));
364 /* same time? order by type of event */
365 if (ret == 0)
366 ret = e1->type - e2->type;
368 /* same time and same event? order by event id */
369 if (ret == 0)
370 ret = e1->event_id - e2->event_id;
372 return ret;
376 static void count_tracks(void)
377 /* sets n_song_tracks */
379 int n;
381 n_song_tracks = 0;
383 for(n = 0; n < n_song_ev; n++) {
384 struct song_ev *e;
386 e = &song[n];
388 if (n_song_tracks < e->trk_id + 1)
389 n_song_tracks = e->trk_id + 1;
394 static void add_eot_events(void)
395 /* travels all events and adds EOT ones */
397 int n, m;
399 for (n = 0; n < n_song_tracks; n++) {
400 struct song_ev *e;
401 double t = -1;
403 for (m = 0; m < n_song_ev; m++) {
404 e = &song[m];
406 /* if this is the track we're looking for
407 and this event time is bigger, store it */
408 if (e->trk_id == n && e->time > t)
409 t = e->time;
412 /* now t has the biggest time; add an EOT event with t */
413 e = add_event(&song, &n_song_ev);
415 e->type = SONG_EV_EOT;
416 e->time = t;
417 e->trk_id = n;
418 e->event_id = n_song_ev - 1;
424 * mute_tracks - Converts track events to NOPs.
425 * @trk_id: Track to be muted. If negative, all buts this will be muted
427 * Converts events to NOP. If @trk_id is positive, all events for that
428 * track id will be converted to NOP; if it's negative, all events BUT
429 * for the ones in that track will be muted.
431 void mute_tracks(int trk_id)
433 int n;
435 for (n = 0; n < n_song_ev; n++) {
436 struct song_ev *e;
438 e = &song[n];
440 /* try only 'real' tracks */
441 if (e->trk_id >= 0) {
442 if (trk_id > 0) {
443 if (e->trk_id == trk_id)
444 e->type = SONG_EV_NOP;
446 else {
447 if (e->trk_id != -trk_id)
448 e->type = SONG_EV_NOP;
456 * song_sort - Sorts the song stream
458 * Sorts the song stream.
460 void song_sort(void)
462 count_tracks();
463 add_eot_events();
465 /* sorts by time, type and event_id */
466 qsort(song, n_song_ev, sizeof(struct song_ev), time_type_eventid_cmp);
468 if (trace)
469 song_trace_events();
474 * song_test_measure_boundary - Does a measure boundary check
475 * @ev_time: event time
476 * @num: meter numerator
477 * @den: meter denominator
479 * Does a measure boundary check. Returns 0 if the event time falls
480 * exactly between two measures, or nonzero otherwise.
482 int song_test_measure_boundary(double ev_time, int num, int den, int line)
484 int ret;
486 if ((ret = ((int) (ev_time * (double) den)) % num))
487 printf("Measure boundary check failed in line %d\n", line);
489 return ret;