Added processing for ss_eff_fader. Also, yacc code for fader effects
[ahxm.git] / ss_song.c
blob8cfba448407e39c9f758f4548e04d90e38a9142f
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 Angel Ortega <angel@triptico.com>
6 ss_song.c - Software synth 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 "core.h"
34 #include "song.h"
35 #include "ss_gen.h"
36 #include "ss_eff.h"
37 #include "ss_ins.h"
38 #include "input.h"
39 #include "output.h"
41 /*******************
42 Data
43 ********************/
45 struct ss_ev_generic
47 song_ev_type type; /* event type */
48 int frame; /* frame number (time) */
49 int trk_id; /* track id */
52 struct ss_ev_note_off
54 song_ev_type type; /* SONG_EV_NOTE_OFF */
55 int frame;
56 int trk_id;
57 int note_id; /* note id */
60 struct ss_ev_note_on
62 song_ev_type type; /* SONG_EV_NOTE_ON */
63 int frame;
64 int trk_id;
65 int note_id; /* note id */
66 int note; /* MIDI-like note number */
67 double vol; /* volume */
70 struct ss_ev_ss_note_on_by_time
72 song_ev_type type; /* SONG_EV_SS_NOTE_ON_BY_TIME */
73 int frame;
74 int trk_id;
75 int note_id; /* note id */
76 int note; /* MIDI-like note (to find the wave) */
77 double len; /* note length (1: whole) */
78 double vol; /* volume */
81 struct ss_ev_ss_sustain
83 song_ev_type type; /* SONG_EV_SS_SUSTAIN */
84 int frame;
85 int trk_id;
86 int sustain; /* sustain time (in frames) */
89 struct ss_ev_ss_channel_map
91 song_ev_type type; /* SONG_EV_SS_CHANNEL_MAP */
92 int frame;
93 int trk_id;
94 float vol[CHANNELS]; /* volumes for each channel */
97 struct ss_ev_ss_wav
99 song_ev_type type; /* SONG_EV_SS_WAV */
100 int frame;
101 int trk_id;
102 char * file; /* path to .wav file */
103 int base; /* MIDI-like base note */
104 int min; /* MIDI-like minimum note */
105 int max; /* MIDI-like maximum note */
108 struct ss_ev_ss_pat
110 song_ev_type type; /* SONG_EV_SS_PAT */
111 int frame;
112 int trk_id;
113 char * file; /* path to .pat file */
116 struct ss_ev_ss_eff
118 song_ev_type type; /* effect type */
119 int frame;
120 int trk_id;
121 int channel; /* channel */
122 double size; /* size of effect */
123 float gain; /* gain */
124 double depth; /* depth */
125 double freq; /* freq */
126 double phase; /* phase */
127 float initial; /* initial vol */
128 float final; /* final vol */
131 union ss_ev
133 struct ss_ev_generic generic;
134 struct ss_ev_note_on note_on;
135 struct ss_ev_note_off note_off;
136 struct ss_ev_ss_note_on_by_time ss_note_on_by_time;
137 struct ss_ev_ss_sustain ss_sustain;
138 struct ss_ev_ss_channel_map ss_channel_map;
139 struct ss_ev_ss_wav ss_wav;
140 struct ss_ev_ss_pat ss_pat;
141 struct ss_ev_ss_eff ss_eff;
144 /* the softsynth song stream */
146 static union ss_ev * _ss_song=NULL;
147 static int _n_ss_ev=0;
150 /* the instruments */
152 #define SONG_INS_NUM 256
153 struct ss_ins song_ins[SONG_INS_NUM];
156 /*******************
157 Code
158 ********************/
160 static void add_ss_ev(union ss_ev * e)
161 /* adds a softsynth song event */
163 _n_ss_ev++;
165 /* reallocs */
166 _ss_song=(union ss_ev *)realloc(_ss_song,
167 _n_ss_ev * sizeof(union ss_ev));
169 /* store */
170 memcpy(&_ss_song[_n_ss_ev - 1], e, sizeof(union ss_ev));
174 static int _ss_ev_cmp(const void * v1, const void * v2)
175 /* softsynth song event compare function for qsort() */
177 struct ss_ev_generic * e1;
178 struct ss_ev_generic * e2;
180 e1=(struct ss_ev_generic *)v1; e2=(struct ss_ev_generic *)v2;
182 if(e1->frame == e2->frame)
183 return(e1->type - e2->type);
185 return(e1->frame - e2->frame);
189 static int _ss_song_convert_events(void)
190 /* converts generic song_ev events to softsynth events */
192 int note_id=1;
193 union song_ev * e;
194 union ss_ev sse;
195 int frame, frame_ac;
196 double fpw, time_ac;
197 int num, den;
198 int n;
199 int b_track=-1;
201 /* resets the ss stream */
202 if(_ss_song != NULL)
204 free(_ss_song);
205 _ss_song=NULL;
208 _n_ss_ev=0;
210 /* sorts the song */
211 song_sort();
213 fpw=0;
214 frame_ac=0;
215 time_ac=0;
216 num=den=4;
218 /* travels the song events generating softsynth song events */
219 for(n=0;n < _n_song_ev;n++)
221 /* gets the song event */
222 e=&_song[n];
224 /* calculates the frame */
225 frame=((e->generic.time - time_ac) * fpw) + frame_ac;
227 /* generic event data */
228 sse.generic.type=e->generic.type;
229 sse.generic.frame=frame;
230 sse.generic.trk_id=e->generic.trk_id;
232 /* account the biggest track seen */
233 if(b_track < e->generic.trk_id) b_track=e->generic.trk_id;
235 switch(e->generic.type)
237 case SONG_EV_TEMPO:
239 /* updates accumulations */
240 frame_ac += frame;
241 time_ac += e->generic.time;
243 /* calculates frames-per-whole based on new tempo */
244 fpw=(double) _frequency * 60.0;
245 fpw /= e->tempo.tempo / 4.0;
247 break;
249 case SONG_EV_METER:
251 /* just store the values */
252 num=e->meter.num;
253 den=e->meter.den;
255 break;
257 case SONG_EV_MEASURE:
259 printf("measure boundary check (must be 0): %d\n",
260 ((int) e->generic.time * num) % den);
262 break;
264 case SONG_EV_NOTE:
266 /* convert to note on / off pairs */
268 sse.note_on.type=SONG_EV_NOTE_ON;
269 sse.note_on.note_id=note_id++;
270 sse.note_on.note=e->note.note;
271 sse.note_on.vol=e->note.vol;
273 add_ss_ev(&sse);
275 frame += (int)(e->note.len * fpw);
277 sse.note_off.type=SONG_EV_NOTE_OFF;
278 sse.note_off.frame=frame;
280 add_ss_ev(&sse);
281 break;
283 case SONG_EV_SS_NOTE_ON_BY_TIME:
285 sse.ss_note_on_by_time.note_id=note_id++;
286 sse.ss_note_on_by_time.note=e->ss_note_by_time.note;
287 sse.ss_note_on_by_time.len=e->ss_note_by_time.len;
288 sse.ss_note_on_by_time.vol=e->ss_note_by_time.vol;
290 add_ss_ev(&sse);
292 frame += (int)(e->ss_note_by_time.len * fpw);
294 sse.note_off.type=SONG_EV_NOTE_OFF;
295 sse.note_off.frame=frame;
297 add_ss_ev(&sse);
298 break;
300 case SONG_EV_SS_WAV:
302 sse.ss_wav.file=e->ss_wav.file;
303 sse.ss_wav.base=e->ss_wav.base;
304 sse.ss_wav.min=e->ss_wav.min;
305 sse.ss_wav.max=e->ss_wav.max;
307 add_ss_ev(&sse);
308 break;
310 case SONG_EV_SS_PAT:
312 sse.ss_pat.file=e->ss_pat.file;
314 add_ss_ev(&sse);
315 break;
317 case SONG_EV_SS_SUSTAIN:
318 case SONG_EV_SS_CHANNEL_MAP:
320 break;
322 case SONG_EV_SS_EFF_DELAY:
323 case SONG_EV_SS_EFF_ECHO:
324 case SONG_EV_SS_EFF_COMB:
325 case SONG_EV_SS_EFF_ALLPASS:
326 case SONG_EV_SS_EFF_FLANGER:
327 case SONG_EV_SS_EFF_WOBBLE:
328 case SONG_EV_SS_EFF_SQWOBBLE:
329 case SONG_EV_SS_EFF_FADER:
330 case SONG_EV_SS_EFF_REVERB:
332 sse.ss_eff.channel=e->ss_eff.channel;
333 sse.ss_eff.size=e->ss_eff.size;
334 sse.ss_eff.gain=e->ss_eff.gain;
335 sse.ss_eff.depth=e->ss_eff.depth;
336 sse.ss_eff.freq=e->ss_eff.freq;
337 sse.ss_eff.phase=e->ss_eff.phase;
338 sse.ss_eff.initial=e->ss_eff.initial;
339 sse.ss_eff.final=e->ss_eff.final;
341 add_ss_ev(&sse);
342 break;
344 case SONG_EV_NOTE_ON:
345 case SONG_EV_NOTE_OFF:
346 case SONG_EV_END:
348 /* never found in generic song streams */
349 break;
353 /* generates an end of event mark, a time after the last one */
354 sse.generic.type=SONG_EV_END;
355 sse.generic.frame=frame + _frequency;
356 add_ss_ev(&sse);
358 /* finally sort */
359 qsort(_ss_song, _n_ss_ev, sizeof(union ss_ev), _ss_ev_cmp);
361 /* return the number of tracks */
362 return(b_track + 1);
366 int generate_ss_song(void)
368 union ss_ev * e;
369 int frame;
370 int go;
371 int n;
372 float output[CHANNELS];
373 int n_tracks;
374 struct ss_ins * i;
376 /* convert the song to ss events */
377 n_tracks=_ss_song_convert_events();
379 frame=0;
380 go=1;
381 e=_ss_song;
383 /* init the instruments */
384 for(n=0;n < n_tracks;n++)
385 ss_ins_init(&song_ins[n], n);
387 /* loop the events */
388 while(go)
390 /* process all events for this exact frame */
391 while(e->generic.frame == frame)
393 /* take the instrument */
394 if(e->generic.trk_id == -1)
395 i=NULL;
396 else
397 i=&song_ins[e->generic.trk_id];
399 switch(e->generic.type)
401 case SONG_EV_NOTE_ON:
403 ss_ins_note_on(i, e->note_on.note,
404 e->note_on.vol, e->note_on.note_id);
406 break;
408 case SONG_EV_SS_NOTE_ON_BY_TIME:
410 break;
412 case SONG_EV_NOTE_OFF:
414 ss_ins_note_off(i, e->note_off.note_id);
416 break;
418 case SONG_EV_SS_SUSTAIN:
419 case SONG_EV_SS_CHANNEL_MAP:
421 break;
423 case SONG_EV_SS_WAV:
426 struct ss_wave w;
428 load_wav_file(&w, e->ss_wav.file,
429 note_frequency(e->ss_wav.base),
430 note_frequency(e->ss_wav.min),
431 note_frequency(e->ss_wav.max));
433 ss_ins_add_layer(i, &w);
436 break;
438 case SONG_EV_SS_PAT:
440 load_pat_file(i, e->ss_pat.file);
441 break;
443 case SONG_EV_SS_EFF_DELAY:
445 ss_eff_delay(&i->effs[e->ss_eff.channel],
446 e->ss_eff.size);
447 break;
449 case SONG_EV_SS_EFF_ECHO:
451 ss_eff_echo(&i->effs[e->ss_eff.channel],
452 e->ss_eff.size, e->ss_eff.gain);
453 break;
455 case SONG_EV_SS_EFF_FADER:
457 ss_eff_fader(&i->effs[e->ss_eff.channel],
458 e->ss_eff.size, e->ss_eff.initial,
459 e->ss_eff.final);
460 break;
462 case SONG_EV_END:
464 go=0;
465 break;
467 case SONG_EV_NOTE:
468 case SONG_EV_TEMPO:
469 case SONG_EV_METER:
470 case SONG_EV_MEASURE:
472 /* never found in ss song streams */
473 break;
476 /* next event */
477 e++;
480 /* reset frame samples */
481 output_init_frame(output);
483 /* generate output from all instruments */
484 for(n=0;n < n_tracks;n++)
485 ss_ins_frame(&song_ins[n], output);
487 /* dump to sampling driver */
488 output_write(output);
490 /* next frame */
491 frame++;
494 return(0);