Updated compiler.y to new coding standards.
[ahxm.git] / song.c
blobb45f96fe224718ed945fe64f4c82c166dc61e059
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 union song_ev *song = NULL;
42 /* number of song events */
43 int n_song_ev = 0;
45 /* solo track (-1, no solo) */
46 int solo_track = -1;
48 /* number of tracks in song */
49 int n_song_tracks = 0;
51 /*******************
52 Code
53 ********************/
55 /**
56 * song_clear - Clears the song stream
58 * Clears the song stream.
60 void song_clear(void)
62 if (song != NULL) {
63 free(song);
64 song = NULL;
67 n_song_ev = 0;
68 n_song_tracks = 0;
72 /**
73 * add_song_ev - Adds a song event to the song stream
74 * @type: event type
75 * @time: event time
76 * @ev: the event
78 * Adds a song event to the song stream.
80 void add_song_ev(song_ev_type type, double time, union song_ev *ev)
82 /* skip tracks if a solo is requested */
83 if (solo_track != -1 && ev->generic.trk_id >= 0 && ev->generic.trk_id != solo_track)
84 return;
86 /* account number of tracks */
87 if (n_song_tracks < ev->generic.trk_id + 1)
88 n_song_tracks = ev->generic.trk_id + 1;
90 GROW(song, n_song_ev, union song_ev);
92 ev->generic.type = type;
93 ev->generic.time = time;
94 ev->generic.event_id = n_song_ev;
96 /* store */
97 memcpy(&song[n_song_ev], ev, sizeof(union song_ev));
99 n_song_ev++;
103 static void song_trace_events(void)
105 union song_ev *e;
106 int n;
108 printf("** GENERIC SONG EVENT DUMP **\n\n");
109 printf("%9s %5s %5s Event and information\n", "Time", "Track", "Ev.ID");
110 printf("---------------------------------------------------------------\n");
112 for (n = 0, e = song; n < n_song_ev; n++, e++) {
113 printf("%9.4lf %5d %5d ",
114 e->generic.time, e->generic.trk_id, e->generic.event_id);
116 switch (e->generic.type) {
117 case SONG_EV_TEMPO:
119 printf("SONG_EV_TEMPO ");
120 printf("TEMPO:%lf", e->tempo.tempo);
121 break;
123 case SONG_EV_METER:
125 printf("SONG_EV_METER ");
126 printf("METER:%d/%d", e->meter.num, e->meter.den);
127 break;
129 case SONG_EV_MEASURE:
131 printf("SONG_EV_MEASURE ");
132 printf("LINE:%d", e->measure.line);
133 break;
135 case SONG_EV_SS_SUSTAIN:
137 printf("SONG_EV_SS_SUSTAIN ");
138 printf("SUSTAIN:%lf", e->ss_sustain.sustain);
139 break;
141 case SONG_EV_SS_VIBRATO:
143 printf("SONG_EV_SS_VIBRATO ");
144 printf("DEPTH:%lf FREQ:%lf",
145 e->ss_vibrato.vib_depth, e->ss_vibrato.vib_freq);
146 break;
148 case SONG_EV_SS_PORTAMENTO:
150 printf("SONG_EV_SS_PORTAMENTO ");
151 printf("VALUE: %lf", e->ss_portamento.portamento);
152 break;
154 case SONG_EV_SS_CHANNEL:
156 printf("SONG_EV_SS_CHANNEL ");
157 printf("CHANNEL:%d VOL:%lf", e->ss_channel.channel, e->ss_channel.vol);
158 break;
160 case SONG_EV_SS_WAV:
162 printf("SONG_EV_SS_WAV ");
163 printf("FILE:'%s' BASE:%d MIN:%d MAX:%d START:%lf END:%lf",
164 e->ss_wav.file, e->ss_wav.base,
165 e->ss_wav.min, e->ss_wav.max,
166 e->ss_wav.loop_start, e->ss_wav.loop_end);
167 break;
169 case SONG_EV_SS_PAT:
171 printf("SONG_EV_SS_PAT ");
172 printf("FILE:'%s'", e->ss_pat.file);
173 break;
175 case SONG_EV_SS_EFF_DELAY:
177 printf("SONG_EV_SS_EFF_DELAY ");
178 printf("CHANNEL:%d ", e->ss_eff.channel);
179 printf("SIZE:%lf ", e->ss_eff.size);
180 break;
182 case SONG_EV_SS_EFF_ECHO:
184 printf("SONG_EV_SS_EFF_ECHO ");
185 printf("CHANNEL:%d ", e->ss_eff.channel);
186 printf("SIZE:%lf ", e->ss_eff.size);
187 printf("GAIN:%f ", e->ss_eff.gain);
188 break;
190 case SONG_EV_SS_EFF_COMB:
192 printf("SONG_EV_SS_EFF_COMB ");
193 printf("CHANNEL:%d ", e->ss_eff.channel);
194 printf("SIZE:%lf ", e->ss_eff.size);
195 printf("GAIN:%f ", e->ss_eff.gain);
196 break;
198 case SONG_EV_SS_EFF_ALLPASS:
200 printf("SONG_EV_SS_EFF_ALLPASS ");
201 printf("CHANNEL:%d ", e->ss_eff.channel);
202 printf("SIZE:%lf ", e->ss_eff.size);
203 printf("GAIN:%f ", e->ss_eff.gain);
204 break;
206 case SONG_EV_SS_EFF_FLANGER:
208 printf("SONG_EV_SS_EFF_FLANGER ");
209 printf("CHANNEL:%d ", e->ss_eff.channel);
210 printf("SIZE:%lf ", e->ss_eff.size);
211 printf("GAIN:%f ", e->ss_eff.gain);
212 printf("DEPTH:%lf ", e->ss_eff.depth);
213 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq, e->ss_eff.phase);
214 break;
216 case SONG_EV_SS_EFF_WOBBLE:
218 printf("SONG_EV_SS_EFF_WOBBLE ");
219 printf("CHANNEL:%d ", e->ss_eff.channel);
220 printf("FREQ:%lf PHASE:%lf GAIN:%lf", e->ss_eff.freq,
221 e->ss_eff.phase, e->ss_eff.gain);
222 break;
224 case SONG_EV_SS_EFF_SQWOBBLE:
226 printf("SONG_EV_SS_EFF_SQWOBBLE ");
227 printf("CHANNEL:%d ", e->ss_eff.channel);
228 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq, e->ss_eff.phase);
229 break;
231 case SONG_EV_SS_EFF_HFWOBBLE:
233 printf("SONG_EV_SS_EFF_HFWOBBLE ");
234 printf("CHANNEL:%d ", e->ss_eff.channel);
235 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq, e->ss_eff.phase);
236 break;
238 case SONG_EV_SS_EFF_FADER:
240 printf("SONG_EV_SS_EFF_FADER ");
241 printf("CHANNEL:%d ", e->ss_eff.channel);
242 printf("SIZE:%lf ", e->ss_eff.size);
243 printf("INITIAL:%f FINAL:%f", e->ss_eff.initial, e->ss_eff.final);
244 break;
246 case SONG_EV_SS_EFF_REVERB:
248 printf("SONG_EV_SS_EFF_REVERB ");
249 printf("CHANNEL:%d ", e->ss_eff.channel);
250 break;
252 case SONG_EV_SS_EFF_FOLDBACK:
254 printf("SONG_EV_SS_EFF_FOLDBACK ");
255 printf("CHANNEL:%d THRESHOLD:%f", e->ss_eff.channel, e->ss_eff.gain);
256 break;
258 case SONG_EV_SS_EFF_ATAN:
260 printf("SONG_EV_SS_EFF_ATAN ");
261 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel, e->ss_eff.gain);
262 break;
264 case SONG_EV_SS_EFF_DISTORT:
266 printf("SONG_EV_SS_EFF_DISTORT ");
267 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel, e->ss_eff.gain);
268 break;
270 case SONG_EV_SS_EFF_OVERDRIVE:
272 printf("SONG_EV_SS_EFF_OVERDRIVE ");
273 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel, e->ss_eff.gain);
274 break;
276 case SONG_EV_SS_EFF_OFF:
278 printf("SONG_EV_SS_EFF_OFF ");
279 printf("CHANNEL:%d ", e->ss_eff.channel);
280 break;
282 case SONG_EV_MIDI_CHANNEL:
284 printf("SONG_EV_MIDI_CHANNEL ");
285 printf("CHANNEL:%d ", e->midi_channel.channel);
286 break;
288 case SONG_EV_MIDI_PROGRAM:
290 printf("SONG_EV_MIDI_PROGRAM ");
291 printf("PROGRAM:%d ", e->midi_program.program);
292 break;
294 case SONG_EV_BACK:
296 printf("SONG_EV_BACK ");
297 printf("LEN:%lf", e->back.len);
298 break;
300 case SONG_EV_NOTE:
302 printf("SONG_EV_NOTE ");
303 printf("MIDI:%d LEN:%lf VOL:%f",
304 e->note.note, e->note.len, e->note.vol);
305 break;
307 case SONG_EV_SS_PITCH_STRETCH:
309 printf("SONG_EV_SS_PITCH_STRETCH ");
310 printf("MIDI:%d LEN:%lf VOL:%f",
311 e->ss_pitch_stretch.note,
312 e->ss_pitch_stretch.len, e->ss_pitch_stretch.vol);
313 break;
315 case SONG_EV_SS_PRINT_WAVE_TEMPO:
317 printf("SONG_EV_SS_PRINT_WAVE_TEMPO ");
318 printf("MIDI:%d LEN:%lf",
319 e->ss_print_wave_tempo.note, e->ss_print_wave_tempo.len);
320 break;
322 case SONG_EV_SONG_INFO:
324 printf("SONG_EV_SONG_INFO ");
325 printf("AUTHOR:'%s' NAME:'%s'",
326 e->song_info.author, e->song_info.name);
327 break;
329 case SONG_EV_EOT:
331 printf("SONG_EV_EOT ");
332 break;
334 default:
335 printf("** Unexpected event type: %d", e->generic.type);
338 printf("\n");
341 printf("\n");
345 static int song_ev_cmp(const void *v1, const void *v2)
346 /* sorts events by time, then type, then event_id */
348 struct song_ev_generic *e1;
349 struct song_ev_generic *e2;
350 int ret;
352 e1 = (struct song_ev_generic *) v1;
353 e2 = (struct song_ev_generic *) v2;
355 ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0));
357 /* same time? order by type of event */
358 if (ret == 0)
359 ret = e1->type - e2->type;
361 /* same time and same event? order by event id */
362 if (ret == 0)
363 ret = e1->event_id - e2->event_id;
365 return ret;
369 static void add_eot_events(void)
370 /* travels all events and adds EOT ones */
372 int n, m;
374 for (n = 0; n < n_song_tracks; n++) {
375 union song_ev *ep;
376 union song_ev e;
377 double t = -1;
379 for (m = 0; m < n_song_ev; m++) {
380 ep = &song[m];
382 /* if this is the track we're looking for
383 and this event time is bigger, store it */
384 if (ep->generic.trk_id == n && ep->generic.time > t)
385 t = ep->generic.time;
388 /* now t has the biggest time; add an EOT event with t */
389 e.generic.trk_id = n;
390 add_song_ev(SONG_EV_EOT, t, &e);
396 * song_sort - Sorts the song stream
398 * Sorts the song stream.
400 void song_sort(void)
402 add_eot_events();
404 /* sorts by time, type and event_id */
405 qsort(song, n_song_ev, sizeof(union song_ev), song_ev_cmp);
407 if (trace)
408 song_trace_events();
413 * song_test_measure_boundary - Does a measure boundary check
414 * @ev_time: event time
415 * @num: meter numerator
416 * @den: meter denominator
418 * Does a measure boundary check. Returns 0 if the event time falls
419 * exactly between two measures, or nonzero otherwise.
421 int song_test_measure_boundary(double ev_time, int num, int den, int line)
423 int ret;
425 if ((ret = ((int) (ev_time * (double) den)) % num))
426 printf("Measure boundary check failed in line %d\n", line);
428 return ret;