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
38 /* maximum number of generators */
39 int ss_gen_num
= SS_MAX_GENERATORS
;
42 static struct ss_gen
*ss_gen_pool
= NULL
;
44 /* free generator queue */
45 static struct ss_gen
*ss_gen_free_queue
= NULL
;
50 static void ss_gen_enqueue(struct ss_gen
**q
, struct ss_gen
*g
)
51 /* Enqueues a generator in a generator queue */
63 void ss_gen_init(void)
64 /* inits the generator pool */
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 */
83 g
->prev
->next
= g
->next
;
88 g
->next
->prev
= g
->prev
;
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
;
100 g
= ss_gen_dequeue(q
, *q
);
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
)
119 if ((g
= ss_gen_pop(&ss_gen_free_queue
)) != NULL
)
120 ss_gen_enqueue(q
, g
);
127 * ss_gen_free - Dequeues a generator and frees it
128 * @q: the queue holding 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
142 * @sustain: sustain time in msecs
144 * Sets sustain for a generator, where @sustain is expressed
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
156 * @attack: attack time in msecs
158 * Sets attack for a generator, where @attack is expressed
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
;
173 * ss_gen_vibrato - Sets vibrato for a 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
;
193 * ss_gen_portamento - Sets portamento for a 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.
211 * @freq: frequency of the sound to be generated
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
,
226 g
->note_id
= note_id
;
230 /* start from the beginning */
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.
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 */
258 /* calculates the delta volume */
259 g
->dsvol
= g
->vol
/ (sample_t
) g
->sustain
;
264 * ss_gen_frame - Generates a frame of samples.
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
[])
280 sample_t l_frame
[SS_MAX_CHANNELS
];
292 /* process vibrato */
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
)
311 /* increment pointer */
314 /* test loop boundaries */
315 if (g
->cursor
> w
->loop_end
) {
317 if (w
->loop_start
< 0)
320 g
->cursor
= w
->loop_start
;
323 /* process sustain */
324 if (g
->note_id
== -1) {
327 if (--g
->sustain
<= 0)
331 /* process portamento */
332 g
->inc
+= g
->portamento
;