Added SONG_EV_SS_PRINT_WAVE_TEMPO case to MIDI song converting to
[ahxm.git] / ss_gen.c
blob7452d1c056028fa9f0d1bbe9bc9e2952b4860006
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 Angel Ortega <angel@triptico.com>
6 ss_gen.c - Software syntesizer's sound generators
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 "annhell.h"
35 /*******************
36 Data
37 ********************/
39 /* maximum number of generators */
40 int ss_gen_num=SS_MAX_GENERATORS;
42 /* generator pool */
43 static struct ss_gen * ss_gen_pool=NULL;
45 /* free generator queue */
46 static struct ss_gen * ss_gen_free_queue=NULL;
49 /*******************
50 Code
51 ********************/
53 static void ss_gen_enqueue(struct ss_gen ** q, struct ss_gen * g)
54 /* Enqueues a generator in a generator queue */
56 g->prev=NULL;
57 g->next=*q;
59 if(*q != NULL)
60 (*q)->prev=g;
62 *q=g;
66 static struct ss_gen * ss_gen_dequeue(struct ss_gen ** q, struct ss_gen * g)
67 /* Dequeues a generator from a generator queue */
69 if(g->prev != NULL)
70 g->prev->next=g->next;
71 else
72 *q=g->next;
74 if(g->next != NULL)
75 g->next->prev=g->prev;
77 return(g);
81 static struct ss_gen * ss_gen_pop(struct ss_gen ** q)
82 /* gets the first enqueued generator from q */
84 struct ss_gen * g=NULL;
86 if(*q != NULL)
87 g=ss_gen_dequeue(q, *q);
89 return(g);
93 /**
94 * ss_gen_alloc - Allocs and enqueues a generator
95 * @q: queue where the generator will be enqueued
97 * Allocs and enqueues a generator into the @q queue.
99 * The new generator is returned, or NULL if the
100 * generator pool is empty.
102 struct ss_gen * ss_gen_alloc(struct ss_gen ** q)
104 int n;
105 struct ss_gen * g;
107 /* first time allocation */
108 if(ss_gen_pool == NULL)
110 ss_gen_pool=(struct ss_gen *) malloc(ss_gen_num *
111 sizeof(struct ss_gen));
113 memset(ss_gen_pool, '\0',
114 ss_gen_num * sizeof(struct ss_gen));
116 /* enqueue all into the free generator queue */
117 for(n=0;n < ss_gen_num;n++)
118 ss_gen_enqueue(&ss_gen_free_queue, &ss_gen_pool[n]);
121 if((g=ss_gen_pop(&ss_gen_free_queue)) != NULL)
122 ss_gen_enqueue(q, g);
124 return(g);
129 * ss_gen_free - Dequeues a generator and frees it
130 * @q: the queue holding the generator
131 * @g: the generator
133 * Dequeues a generator and sends it back to the generator pool.
135 void ss_gen_free(struct ss_gen ** q, struct ss_gen * g)
137 ss_gen_enqueue(&ss_gen_free_queue, ss_gen_dequeue(q, g));
142 * ss_gen_sustain - Sets sustain for a generator
143 * @g: the generator
144 * @sustain: sustain time in msecs
146 * Sets sustain for a generator, where @sustain is expressed
147 * in milliseconds.
149 void ss_gen_sustain(struct ss_gen * g, double sustain)
151 g->sustain=MS2F(sustain);
156 * ss_gen_vibrato - Sets vibrato for a generator
157 * @g: the generator
158 * @depth: vibrato depth in msecs
159 * @freq: vibrato frequency
161 * Sets vibrato for a generator, with a @depth expressed in
162 * milliseconds and a frequency @freq expressed in hzs.
164 void ss_gen_vibrato(struct ss_gen * g, double depth, double freq)
166 /* good freq: 6 Hz (0.001) */
167 /* good depth: 1/6 semitone (20, 30 frames) */
169 g->vib_depth=MS2F(depth);
170 g->vib_inc=( 6.28 * freq ) / (double)ss_frequency;
171 g->vibrato=0.0;
176 * ss_gen_play - Activates a generator.
177 * @g: generator
178 * @freq: frequency of the sound to be generated
179 * @vol: volume
180 * @note_id: note id
181 * @w: the wave
183 * Activates a generator, usually as a response for a 'note on'
184 * message from an upper level. The wave @w holds all the sample
185 * data (PCM data, base frequency, etc.), @freq is the desired
186 * frequency, @vol the volume and @note_id a positive, unique
187 * identifier for the note.
189 void ss_gen_play(struct ss_gen * g, double freq, float vol, int note_id,
190 struct ss_wave * w)
192 /* store data */
193 g->note_id=note_id;
194 g->vol=vol;
195 g->w=w;
197 /* start from the beginning */
198 g->cursor=0;
200 /* calculate increment */
201 g->inc=freq / w->base_freq;
202 g->inc *= (double) w->s_rate / (double) ss_frequency;
204 /* default sustain, vibrato and portamento */
205 ss_gen_sustain(g, 50.0);
206 ss_gen_vibrato(g, 0.0, 0.0);
207 g->portamento=0;
212 * ss_gen_release - Releases a generator.
213 * @g: the generator
215 * Releases a generator, usually as a response for a 'note off'
216 * message from an upper level. The generator enters SS_GEN_RELEASED
217 * mode, which starts generating sustain data until it's over.
219 void ss_gen_release(struct ss_gen * g)
221 /* note needs not be tracked anymore */
222 g->note_id=-1;
224 /* calculates the delta volume */
225 g->dvol=g->vol / (float) g->sustain;
230 * ss_gen_frame - Generates a frame of samples.
231 * @g: the generator
232 * @n_channels: the desired number of channels
233 * @frame: array where the output samples will be stored
235 * Generates a frame of samples from the @g generator, that will be stored
236 * in the @frame array. If @n_channels is greater than the number
237 * of channels the generator has, they are sequentially spread.
239 * Returns non-zero if the generator is stopped and should be freed.
241 int ss_gen_frame(struct ss_gen * g, int n_channels, float frame[])
243 int n;
244 int to_free=0;
245 double v;
246 float l_frame[SS_MAX_CHANNELS];
247 struct ss_wave * w;
249 v=g->cursor;
250 w=g->w;
252 /* process vibrato */
253 if(g->vib_inc)
255 g->vibrato += g->vib_inc;
256 v += sin(g->vibrato) * g->vib_depth;
259 /* add samples to frame */
260 for(n=0;n < w->n_channels;n++)
261 l_frame[n] = ss_get_sample(w->wave[n], w->size, v) * g->vol;
263 /* spread the frame into n_channels */
264 for(n=0;n < n_channels;n++)
265 frame[n] += l_frame[n % w->n_channels];
267 /* increment pointer */
268 g->cursor += g->inc;
270 /* test loop boundaries */
271 if(g->cursor > w->loop_end)
273 /* loop mode? */
274 if(w->loop_start < 0)
275 to_free=1;
276 else
277 g->cursor=w->loop_start;
280 /* process sustain */
281 if(g->note_id == -1)
283 g->vol -= g->dvol;
285 if(--g->sustain <= 0)
286 to_free=1;
289 /* process portamento */
290 g->inc += g->portamento;
292 return(to_free);