New file .gitignore.
[ahxm.git] / song.c
blobbe03f35d1117375379e03d6b4bdb524fab51cfc5
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)
64 free(song);
65 song = NULL;
68 n_song_ev = 0;
69 n_song_tracks = 0;
73 /**
74 * add_song_ev - Adds a song event to the song stream
75 * @type: event type
76 * @time: event time
77 * @ev: the event
79 * Adds a song event to the song stream.
81 void add_song_ev(song_ev_type type, double time, union song_ev * ev)
83 /* skip tracks if a solo is requested */
84 if(solo_track != -1 && ev->generic.trk_id >= 0 &&
85 ev->generic.trk_id != solo_track)
86 return;
88 /* account number of tracks */
89 if(n_song_tracks < ev->generic.trk_id + 1)
90 n_song_tracks = ev->generic.trk_id + 1;
92 GROW(song, n_song_ev, union song_ev);
94 ev->generic.type = type;
95 ev->generic.time = time;
96 ev->generic.event_id = n_song_ev;
98 /* store */
99 memcpy(&song[n_song_ev], ev, sizeof(union song_ev));
101 n_song_ev++;
105 static void song_trace_events(void)
107 union song_ev * e;
108 int n;
110 printf("** GENERIC SONG EVENT DUMP **\n\n");
111 printf("%9s %5s %5s Event and information\n",
112 "Time", "Track", "Ev.ID");
113 printf("---------------------------------------------------------------\n");
115 for(n = 0, e = song;n < n_song_ev;n++, e++)
117 printf("%9.4lf %5d %5d ",
118 e->generic.time, e->generic.trk_id,
119 e->generic.event_id);
121 switch(e->generic.type)
123 case SONG_EV_TEMPO:
125 printf("SONG_EV_TEMPO ");
126 printf("TEMPO:%lf", e->tempo.tempo);
127 break;
129 case SONG_EV_METER:
131 printf("SONG_EV_METER ");
132 printf("METER:%d/%d", e->meter.num, e->meter.den);
133 break;
135 case SONG_EV_MEASURE:
137 printf("SONG_EV_MEASURE ");
138 printf("LINE:%d", e->measure.line);
139 break;
141 case SONG_EV_SS_SUSTAIN:
143 printf("SONG_EV_SS_SUSTAIN ");
144 printf("SUSTAIN:%lf", e->ss_sustain.sustain);
145 break;
147 case SONG_EV_SS_VIBRATO:
149 printf("SONG_EV_SS_VIBRATO ");
150 printf("DEPTH:%lf FREQ:%lf",
151 e->ss_vibrato.vib_depth,
152 e->ss_vibrato.vib_freq);
153 break;
155 case SONG_EV_SS_PORTAMENTO:
157 printf("SONG_EV_SS_PORTAMENTO ");
158 printf("VALUE: %lf", e->ss_portamento.portamento);
159 break;
161 case SONG_EV_SS_CHANNEL:
163 printf("SONG_EV_SS_CHANNEL ");
164 printf("CHANNEL:%d VOL:%lf",
165 e->ss_channel.channel,
166 e->ss_channel.vol);
167 break;
169 case SONG_EV_SS_WAV:
171 printf("SONG_EV_SS_WAV ");
172 printf("FILE:'%s' BASE:%d MIN:%d MAX:%d START:%lf END:%lf",
173 e->ss_wav.file, e->ss_wav.base,
174 e->ss_wav.min, e->ss_wav.max,
175 e->ss_wav.loop_start, e->ss_wav.loop_end);
176 break;
178 case SONG_EV_SS_PAT:
180 printf("SONG_EV_SS_PAT ");
181 printf("FILE:'%s'", e->ss_pat.file);
182 break;
184 case SONG_EV_SS_EFF_DELAY:
186 printf("SONG_EV_SS_EFF_DELAY ");
187 printf("CHANNEL:%d ", e->ss_eff.channel);
188 printf("SIZE:%lf ", e->ss_eff.size);
189 break;
191 case SONG_EV_SS_EFF_ECHO:
193 printf("SONG_EV_SS_EFF_ECHO ");
194 printf("CHANNEL:%d ", e->ss_eff.channel);
195 printf("SIZE:%lf ", e->ss_eff.size);
196 printf("GAIN:%f ", e->ss_eff.gain);
197 break;
199 case SONG_EV_SS_EFF_COMB:
201 printf("SONG_EV_SS_EFF_COMB ");
202 printf("CHANNEL:%d ", e->ss_eff.channel);
203 printf("SIZE:%lf ", e->ss_eff.size);
204 printf("GAIN:%f ", e->ss_eff.gain);
205 break;
207 case SONG_EV_SS_EFF_ALLPASS:
209 printf("SONG_EV_SS_EFF_ALLPASS ");
210 printf("CHANNEL:%d ", e->ss_eff.channel);
211 printf("SIZE:%lf ", e->ss_eff.size);
212 printf("GAIN:%f ", e->ss_eff.gain);
213 break;
215 case SONG_EV_SS_EFF_FLANGER:
217 printf("SONG_EV_SS_EFF_FLANGER ");
218 printf("CHANNEL:%d ", e->ss_eff.channel);
219 printf("SIZE:%lf ", e->ss_eff.size);
220 printf("GAIN:%f ", e->ss_eff.gain);
221 printf("DEPTH:%lf ", e->ss_eff.depth);
222 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq,
223 e->ss_eff.phase);
224 break;
226 case SONG_EV_SS_EFF_WOBBLE:
228 printf("SONG_EV_SS_EFF_WOBBLE ");
229 printf("CHANNEL:%d ", e->ss_eff.channel);
230 printf("FREQ:%lf PHASE:%lf GAIN:%lf", e->ss_eff.freq,
231 e->ss_eff.phase, e->ss_eff.gain);
232 break;
234 case SONG_EV_SS_EFF_SQWOBBLE:
236 printf("SONG_EV_SS_EFF_SQWOBBLE ");
237 printf("CHANNEL:%d ", e->ss_eff.channel);
238 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq,
239 e->ss_eff.phase);
240 break;
242 case SONG_EV_SS_EFF_HFWOBBLE:
244 printf("SONG_EV_SS_EFF_HFWOBBLE ");
245 printf("CHANNEL:%d ", e->ss_eff.channel);
246 printf("FREQ:%lf PHASE:%lf", e->ss_eff.freq,
247 e->ss_eff.phase);
248 break;
250 case SONG_EV_SS_EFF_FADER:
252 printf("SONG_EV_SS_EFF_FADER ");
253 printf("CHANNEL:%d ", e->ss_eff.channel);
254 printf("SIZE:%lf ", e->ss_eff.size);
255 printf("INITIAL:%f FINAL:%f", e->ss_eff.initial,
256 e->ss_eff.final);
257 break;
259 case SONG_EV_SS_EFF_REVERB:
261 printf("SONG_EV_SS_EFF_REVERB ");
262 printf("CHANNEL:%d ", e->ss_eff.channel);
263 break;
265 case SONG_EV_SS_EFF_FOLDBACK:
267 printf("SONG_EV_SS_EFF_FOLDBACK ");
268 printf("CHANNEL:%d THRESHOLD:%f", e->ss_eff.channel,
269 e->ss_eff.gain);
270 break;
272 case SONG_EV_SS_EFF_ATAN:
274 printf("SONG_EV_SS_EFF_ATAN ");
275 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel,
276 e->ss_eff.gain);
277 break;
279 case SONG_EV_SS_EFF_DISTORT:
281 printf("SONG_EV_SS_EFF_DISTORT ");
282 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel,
283 e->ss_eff.gain);
284 break;
286 case SONG_EV_SS_EFF_OVERDRIVE:
288 printf("SONG_EV_SS_EFF_OVERDRIVE ");
289 printf("CHANNEL:%d GAIN:%f", e->ss_eff.channel,
290 e->ss_eff.gain);
291 break;
293 case SONG_EV_SS_EFF_OFF:
295 printf("SONG_EV_SS_EFF_OFF ");
296 printf("CHANNEL:%d ", e->ss_eff.channel);
297 break;
299 case SONG_EV_MIDI_CHANNEL:
301 printf("SONG_EV_MIDI_CHANNEL ");
302 printf("CHANNEL:%d ", e->midi_channel.channel);
303 break;
305 case SONG_EV_MIDI_PROGRAM:
307 printf("SONG_EV_MIDI_PROGRAM ");
308 printf("PROGRAM:%d ", e->midi_program.program);
309 break;
311 case SONG_EV_BACK:
313 printf("SONG_EV_BACK ");
314 printf("LEN:%lf", e->back.len);
315 break;
317 case SONG_EV_NOTE:
319 printf("SONG_EV_NOTE ");
320 printf("MIDI:%d LEN:%lf VOL:%f",
321 e->note.note, e->note.len, e->note.vol);
322 break;
324 case SONG_EV_SS_PITCH_STRETCH:
326 printf("SONG_EV_SS_PITCH_STRETCH ");
327 printf("MIDI:%d LEN:%lf VOL:%f",
328 e->ss_pitch_stretch.note,
329 e->ss_pitch_stretch.len,
330 e->ss_pitch_stretch.vol);
331 break;
333 case SONG_EV_SS_PRINT_WAVE_TEMPO:
335 printf("SONG_EV_SS_PRINT_WAVE_TEMPO ");
336 printf("MIDI:%d LEN:%lf",
337 e->ss_print_wave_tempo.note,
338 e->ss_print_wave_tempo.len);
339 break;
341 case SONG_EV_SONG_INFO:
343 printf("SONG_EV_SONG_INFO ");
344 printf("AUTHOR:'%s' NAME:'%s'",
345 e->song_info.author,
346 e->song_info.name);
347 break;
349 case SONG_EV_EOT:
351 printf("SONG_EV_EOT ");
352 break;
354 default:
355 printf("** Unexpected event type: %d",
356 e->generic.type);
359 printf("\n");
362 printf("\n");
366 static int song_ev_cmp(const void * v1, const void * v2)
367 /* sorts events by time, then type, then event_id */
369 struct song_ev_generic * e1;
370 struct song_ev_generic * e2;
371 int ret;
373 e1 = (struct song_ev_generic *)v1; e2 = (struct song_ev_generic *)v2;
375 ret = (int) ((e1->time * 10000.0) - (e2->time * 10000.0));
377 /* same time? order by type of event */
378 if(ret == 0)
379 ret = e1->type - e2->type;
381 /* same time and same event? order by event id */
382 if(ret == 0)
383 ret = e1->event_id - e2->event_id;
385 return(ret);
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++)
396 union song_ev * ep;
397 union song_ev e;
398 double t = -1;
400 for(m = 0;m < n_song_ev;m++)
402 ep = &song[m];
404 /* if this is the track we're looking for
405 and this event time is bigger, store it */
406 if(ep->generic.trk_id == n && ep->generic.time > t)
407 t = ep->generic.time;
410 /* now t has the biggest time; add an EOT event with t */
411 e.generic.trk_id = n;
412 add_song_ev(SONG_EV_EOT, t, &e);
418 * song_sort - Sorts the song stream
420 * Sorts the song stream.
422 void song_sort(void)
424 add_eot_events();
426 /* sorts by time, type and event_id */
427 qsort(song, n_song_ev, sizeof(union song_ev), song_ev_cmp);
429 if(trace) song_trace_events();
434 * song_test_measure_boundary - Does a measure boundary check
435 * @ev_time: event time
436 * @num: meter numerator
437 * @den: meter denominator
439 * Does a measure boundary check. Returns 0 if the event time falls
440 * exactly between two measures, or nonzero otherwise.
442 int song_test_measure_boundary(double ev_time, int num, int den, int line)
444 int ret;
446 if((ret = ((int)(ev_time * (double) den)) % num))
447 printf("Measure boundary check failed in line %d\n", line);
449 return(ret);