Print the configured drivers in config and help.
[ahxm.git] / ss_gen.c
blob648e1af00f089df7f51e948d80f308c6ebc0d6e3
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2008 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 "ahxm.h"
36 /** data **/
38 /* maximum number of generators */
39 int ss_gen_num = SS_MAX_GENERATORS;
41 /* generator pool */
42 static struct ss_gen *ss_gen_pool = NULL;
44 /* free generator queue */
45 static struct ss_gen *ss_gen_free_queue = NULL;
48 /** code **/
50 static void ss_gen_enqueue(struct ss_gen **q, struct ss_gen *g)
51 /* Enqueues a generator in a generator queue */
53 g->prev = NULL;
54 g->next = *q;
56 if (*q != NULL)
57 (*q)->prev = g;
59 *q = g;
63 void ss_gen_init(void)
64 /* inits the generator pool */
66 int n;
68 ss_gen_pool = (struct ss_gen *) realloc(ss_gen_pool, ss_gen_num *
69 sizeof(struct ss_gen));
71 memset(ss_gen_pool, '\0', ss_gen_num * sizeof(struct ss_gen));
73 /* enqueue all into the free generator queue */
74 for (n = 0; n < ss_gen_num; n++)
75 ss_gen_enqueue(&ss_gen_free_queue, &ss_gen_pool[n]);
79 static struct ss_gen *ss_gen_dequeue(struct ss_gen **q, struct ss_gen *g)
80 /* Dequeues a generator from a generator queue */
82 if (g->prev != NULL)
83 g->prev->next = g->next;
84 else
85 *q = g->next;
87 if (g->next != NULL)
88 g->next->prev = g->prev;
90 return g;
94 static struct ss_gen *ss_gen_pop(struct ss_gen **q)
95 /* gets the first enqueued generator from q */
97 struct ss_gen *g = NULL;
99 if (*q != NULL)
100 g = ss_gen_dequeue(q, *q);
102 return g;
107 * ss_gen_alloc - Allocs and enqueues a generator
108 * @q: queue where the generator will be enqueued
110 * Allocs and enqueues a generator into the @q queue.
112 * The new generator is returned, or NULL if the
113 * generator pool is empty.
115 struct ss_gen *ss_gen_alloc(struct ss_gen **q)
117 struct ss_gen *g;
119 if ((g = ss_gen_pop(&ss_gen_free_queue)) != NULL)
120 ss_gen_enqueue(q, g);
122 return g;
127 * ss_gen_free - Dequeues a generator and frees it
128 * @q: the queue holding the generator
129 * @g: the generator
131 * Dequeues a generator and sends it back to the generator pool.
133 void ss_gen_free(struct ss_gen **q, struct ss_gen *g)
135 ss_gen_enqueue(&ss_gen_free_queue, ss_gen_dequeue(q, g));
140 * ss_gen_sustain - Sets sustain for a generator
141 * @g: the generator
142 * @sustain: sustain time in msecs
144 * Sets sustain for a generator, where @sustain is expressed
145 * in milliseconds.
147 void ss_gen_sustain(struct ss_gen *g, double sustain)
149 g->sustain = MS2F(sustain);
154 * ss_gen_attack - Sets attack for a generator
155 * @g: the generator
156 * @attack: attack time in msecs
158 * Sets attack for a generator, where @attack is expressed
159 * in milliseconds.
161 void ss_gen_attack(struct ss_gen *g, double attack)
163 if ((g->attack = MS2F(attack)) > 0) {
164 /* calculates the delta volume */
165 g->davol = g->vol / (sample_t) g->attack;
167 g->vol = 0.0;
173 * ss_gen_vibrato - Sets vibrato for a generator
174 * @g: the generator
175 * @depth: vibrato depth in msecs
176 * @freq: vibrato frequency
178 * Sets vibrato for a generator, with a @depth expressed in
179 * milliseconds and a frequency @freq expressed in hzs.
181 void ss_gen_vibrato(struct ss_gen *g, double depth, double freq)
183 /* good freq: 6 Hz (0.001) */
184 /* good depth: 1/6 semitone (20, 30 frames) */
186 g->vib_depth = MS2F(depth);
187 g->vib_inc = (6.28 * freq) / (double) ss_frequency;
188 g->vibrato = 0.0;
193 * ss_gen_portamento - Sets portamento for a generator
194 * @g: the generator
195 * @portamento: portamento value
197 * Sets portamento for a generator, where @portamento is an
198 * increment to the internal cursor of the wave. This value must
199 * be very small. Negative values will make the frequency slide
200 * down and positive slide up.
202 void ss_gen_portamento(struct ss_gen *g, double portamento)
204 g->portamento = portamento;
209 * ss_gen_play - Activates a generator.
210 * @g: generator
211 * @freq: frequency of the sound to be generated
212 * @vol: volume
213 * @note_id: note id
214 * @w: the wave
216 * Activates a generator, usually as a response for a 'note on'
217 * message from an upper level. The wave @w holds all the sample
218 * data (PCM data, base frequency, etc.), @freq is the desired
219 * frequency, @vol the volume and @note_id a positive, unique
220 * identifier for the note.
222 void ss_gen_play(struct ss_gen *g, double freq, sample_t vol, int note_id,
223 struct ss_wave *w)
225 /* store data */
226 g->note_id = note_id;
227 g->vol = vol;
228 g->w = w;
230 /* start from the beginning */
231 g->cursor = 0;
233 /* calculate increment */
234 g->inc = freq / w->base_freq;
235 g->inc *= (double) w->s_rate / (double) ss_frequency;
237 /* default sustain, vibrato and portamento */
238 ss_gen_sustain(g, 50.0);
239 ss_gen_attack(g, 0.0);
240 ss_gen_vibrato(g, 0.0, 0.0);
241 ss_gen_portamento(g, 0.0);
246 * ss_gen_release - Releases a generator.
247 * @g: the generator
249 * Releases a generator, usually as a response for a 'note off'
250 * message from an upper level. The generator enters SS_GEN_RELEASED
251 * mode, which starts generating sustain data until it's over.
253 void ss_gen_release(struct ss_gen *g)
255 /* note needs not be tracked anymore */
256 g->note_id = -1;
258 /* calculates the delta volume */
259 g->dsvol = g->vol / (sample_t) g->sustain;
264 * ss_gen_frame - Generates a frame of samples.
265 * @g: the generator
266 * @n_channels: the desired number of channels
267 * @frame: array where the output samples will be stored
269 * Generates a frame of samples from the @g generator, that will be stored
270 * in the @frame array. If @n_channels is greater than the number
271 * of channels the generator has, they are sequentially spread.
273 * Returns non-zero if the generator is stopped and should be freed.
275 int ss_gen_frame(struct ss_gen *g, int n_channels, sample_t frame[])
277 int n, m;
278 int to_free = 0;
279 double v;
280 sample_t l_frame[SS_MAX_CHANNELS];
281 struct ss_wave *w;
283 v = g->cursor;
284 w = g->w;
286 /* process attack */
287 if (g->attack) {
288 g->vol += g->davol;
289 g->attack--;
292 /* process vibrato */
293 if (g->vib_inc) {
294 g->vibrato += g->vib_inc;
295 v += sin(g->vibrato) * g->vib_depth;
298 /* add samples to frame */
299 for (n = 0; n < w->n_channels; n++)
300 l_frame[n] = ss_get_sample(w, n, v) * g->vol;
302 /* spread the frame into n_channels */
303 for (n = w->first_channel, m = 0; n < n_channels; n++) {
304 frame[n] += l_frame[m];
306 n += w->skip_channels;
307 if (++m == w->n_channels)
308 m = 0;
311 /* increment pointer */
312 g->cursor += g->inc;
314 /* test loop boundaries */
315 if (g->cursor > w->loop_end) {
316 /* loop mode? */
317 if (w->loop_start < 0)
318 to_free = 1;
319 else
320 g->cursor = w->loop_start;
323 /* process sustain */
324 if (g->note_id == -1) {
325 g->vol -= g->dsvol;
327 if (--g->sustain <= 0)
328 to_free = 1;
331 /* process portamento */
332 g->inc += g->portamento;
334 return to_free;