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
54 ss_ev_type type
; /* event type */
55 int frame
; /* frame number (time) */
56 int trk_id
; /* track id */
61 ss_ev_type type
; /* EV_NOTE_OFF */
64 int note_id
; /* note id */
69 ss_ev_type type
; /* EV_NOTE_ON */
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 */
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 */
92 int sustain
; /* sustain time (in frames) */
95 struct ss_ev_ss_channel_map
97 ss_ev_type type
; /* EV_SS_CHANNEL_MAP */
100 float vol
[CHANNELS
]; /* volumes for each channel */
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;
120 ********************/
122 static void add_ss_ev(union ss_ev
* e
)
123 /* adds a softsynth song event */
128 _ss_song
=(union ss_ev
*)realloc(_ss_song
,
129 _n_ss_ev
* sizeof(union ss_ev
));
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 */
162 /* resets the ss stream */
179 /* travels the song events generating softsynth song events */
180 for(n
=0;n
< _n_song_ev
;n
++)
182 /* gets the song event */
185 /* calculates the frame */
186 frame
=((e
->generic
.time
- time_ac
) * fpw
) + frame_ac
;
188 switch(e
->generic
.type
)
192 /* updates accumulations */
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;
204 /* just store the values */
210 case SONG_EV_MEASURE
:
212 printf("measure boundary check (must be 0): %d\n",
213 ((int) e
->generic
.time
* num
) % den
);
219 sse
.note_on
.type
=EV_NOTE_ON
;
220 sse
.note_on
.frame
=frame
;
221 sse
.note_on
.trk_id
=e
->note
.trk_id
;
222 sse
.note_on
.note_id
=note_id
++;
223 sse
.note_on
.note
=e
->note
.note
;
224 sse
.note_on
.vol
=e
->note
.vol
;
228 sse
.note_off
.type
=EV_NOTE_OFF
;
229 sse
.note_off
.frame
+= (int)(e
->note
.len
* fpw
);
235 case SONG_EV_SS_NOTE
:
237 sse
.ss_note_on
.type
=EV_SS_NOTE_ON
;
238 sse
.ss_note_on
.frame
=frame
;
239 sse
.ss_note_on
.trk_id
=e
->ss_note
.trk_id
;
240 sse
.ss_note_on
.note_id
=note_id
++;
241 sse
.ss_note_on
.freq
=e
->ss_note
.freq
;
242 sse
.ss_note_on
.vol
=e
->ss_note
.vol
;
246 sse
.note_off
.type
=EV_NOTE_OFF
;
247 sse
.note_off
.frame
+= (int)(e
->note
.len
* fpw
);
255 /* generates an end of event mark, a time after the last one */
256 sse
.generic
.type
=EV_END
;
257 sse
.generic
.frame
=frame
+ _frequency
;
261 qsort(_ss_song
, _n_ss_ev
, sizeof(union ss_ev
), _ss_ev_cmp
);
265 int generate_ss_song(void)
271 /* convert the song to ss events */
272 _ss_song_convert_events();
278 /* loop the events */
281 /* process all events for this exact frame */
282 while(e
->generic
.frame
== frame
)
284 switch(e
->generic
.type
)
290 case EV_SS_CHANNEL_MAP
:
304 /* generate output from all instruments */