Added a new source file, ss_song.c, to hold the old "event2" stream,
[ahxm.git] / ss_song.c
blob040a4036d729ffecbffa7fb25466e67dfa1e8986
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"
36 /*******************
37 Data
38 ********************/
40 typedef enum
42 EV_SUSTAIN,
43 EV_CHANNEL_MAP,
45 EV_NOTE_OFF,
46 EV_NOTE_ON,
47 EV_SS_NOTE_ON,
49 EV_END
50 } ss_ev_type;
52 struct ss_ev_generic
54 ss_ev_type type; /* event type */
55 int frame; /* frame number (time) */
56 int trk_id; /* track id */
59 struct ss_ev_note_off
61 ss_ev_type type; /* EV_NOTE_OFF */
62 int frame;
63 int trk_id;
64 int note_id; /* note id */
67 struct ss_ev_note_on
69 ss_ev_type type; /* EV_NOTE_ON */
70 int frame;
71 int trk_id;
72 int note_id; /* note id */
73 int note; /* MIDI-like note number */
74 double vol; /* volume */
77 struct ss_ev_ss_note_on
79 ss_ev_type type; /* EV_SS_NOTE_ON */
80 int frame;
81 int trk_id;
82 int note_id; /* note id */
83 double freq; /* note frequency */
84 double vol; /* volume */
87 struct ss_ev_ss_sustain
89 ss_ev_type type; /* EV_SS_SUSTAIN */
90 int frame;
91 int trk_id;
92 int sustain; /* sustain time (in frames) */
95 struct ss_ev_ss_channel_map
97 ss_ev_type type; /* EV_SS_CHANNEL_MAP */
98 int frame;
99 int trk_id;
100 float vol[CHANNELS]; /* volumes for each channel */
103 union ss_ev
105 struct ss_ev_generic generic;
106 struct ss_ev_note_on note_on;
107 struct ss_ev_note_off note_off;
108 struct ss_ev_ss_note_on ss_note_on;
109 struct ss_ev_ss_sustain ss_sustain;
110 struct ss_ev_ss_channel_map ss_channel_map;
113 /* the softsynth song stream */
115 static union ss_ev * _ss_song=NULL;
116 static int _n_ss_ev=0;
118 /*******************
119 Code
120 ********************/
122 static void add_ss_ev(union ss_ev * e)
123 /* adds a softsynth song event */
125 _n_ss_ev++;
127 /* reallocs */
128 _ss_song=(union ss_ev *)realloc(_ss_song,
129 _n_ss_ev * sizeof(union ss_ev));
131 /* store */
132 memcpy(&_ss_song[_n_ss_ev - 1], e, sizeof(union ss_ev));
136 static int _ss_ev_cmp(const void * v1, const void * v2)
137 /* softsynth song event compare function for qsort() */
139 struct ss_ev_generic * e1;
140 struct ss_ev_generic * e2;
142 e1=(struct ss_ev_generic *)v1; e2=(struct ss_ev_generic *)v2;
144 if(e1->frame == e2->frame)
145 return(e1->type - e2->type);
147 return(e1->frame - e2->frame);
151 static void _ss_song_convert_events(void)
152 /* converts generic song_ev events to softsynth events */
154 int note_id=1;
155 union song_ev * e;
156 union ss_ev sse;
157 int frame, frame_ac;
158 double fpw, time_ac;
159 int num, den;
160 int n;
162 /* resets the ss stream */
163 if(_ss_song != NULL)
165 free(_ss_song);
166 _ss_song=0;
169 _n_ss_ev=0;
171 /* sorts the song */
172 song_sort();
174 fpw=0;
175 frame_ac=0;
176 time_ac=0;
177 num=den=4;
179 /* travels the song events generating softsynth song events */
180 for(n=0;n < _n_song_ev;n++)
182 /* gets the song event */
183 e=&_song[n];
185 /* calculates the frame */
186 frame=((e->generic.time - time_ac) * fpw) + frame_ac;
188 switch(e->generic.type)
190 case SONG_EV_TEMPO:
192 /* updates accumulations */
193 frame_ac += frame;
194 time_ac += e->generic.time;
196 /* calculates frames-per-whole based on new tempo */
197 fpw=(double) _frequency * 60.0;
198 fpw /= e->tempo.tempo / 4.0;
200 break;
202 case SONG_EV_METER:
204 /* just store the values */
205 num=e->meter.num;
206 den=e->meter.den;
208 break;
210 case SONG_EV_MEASURE:
213 measure boundary checks will be done with
215 d=_time * (double) _meas_num / (double) _meas_den;
217 if(d != ceil(d))
219 _c_cerror("measure-mark-error", mode);
220 break;
224 break;
226 case SONG_EV_NOTE:
228 sse.note_on.type=EV_NOTE_ON;
229 sse.note_on.frame=frame;
230 sse.note_on.trk_id=e->note.trk_id;
231 sse.note_on.note_id=note_id++;
232 sse.note_on.note=e->note.note;
233 sse.note_on.vol=e->note.vol;
235 add_ss_ev(&sse);
237 sse.note_off.type=EV_NOTE_OFF;
238 sse.note_off.frame += (int)(e->note.len * fpw);
240 add_ss_ev(&sse);
242 break;
244 case SONG_EV_SS_NOTE:
246 sse.ss_note_on.type=EV_SS_NOTE_ON;
247 sse.ss_note_on.frame=frame;
248 sse.ss_note_on.trk_id=e->ss_note.trk_id;
249 sse.ss_note_on.note_id=note_id++;
250 sse.ss_note_on.freq=e->ss_note.freq;
251 sse.ss_note_on.vol=e->ss_note.vol;
253 add_ss_ev(&sse);
255 sse.note_off.type=EV_NOTE_OFF;
256 sse.note_off.frame += (int)(e->note.len * fpw);
258 add_ss_ev(&sse);
260 break;
264 /* generates an end of event mark, a time after the last one */
265 sse.generic.type=EV_END;
266 sse.generic.frame=frame + _frequency;
267 add_ss_ev(&sse);
269 /* finally sort */
270 qsort(_ss_song, _n_ss_ev, sizeof(union ss_ev), _ss_ev_cmp);
274 int generate_ss_song(void)
276 _ss_song_convert_events();
278 return(0);