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
40 /* number of generators */
41 int ss_gen_num
=SS_GEN_NUM
;
44 static struct ss_gen
* ss_gen_pool
=NULL
;
46 /* free generator queue */
47 static struct ss_gen
* ss_gen_free_queue
=NULL
;
54 static void ss_gen_enqueue(struct ss_gen
** q
, struct ss_gen
* g
)
55 /* Enqueues a generator in a generator queue */
67 static struct ss_gen
* ss_gen_dequeue(struct ss_gen
** q
, struct ss_gen
* g
)
68 /* Dequeues a generator from a generator queue */
71 g
->prev
->next
=g
->next
;
76 g
->next
->prev
=g
->prev
;
82 static struct ss_gen
* ss_gen_pop(struct ss_gen
** q
)
83 /* gets the first enqueued generator from q */
85 struct ss_gen
* g
=NULL
;
88 g
=ss_gen_dequeue(q
, *q
);
95 * ss_gen_alloc - Allocs and enqueues a generator
96 * @q: queue where the generator will be enqueued
98 * Allocs and enqueues a generator into the @q queue.
100 * The new generator is returned, or NULL if the
101 * generator pool is empty.
103 struct ss_gen
* ss_gen_alloc(struct ss_gen
** q
)
108 /* first time allocation */
109 if(ss_gen_pool
== NULL
)
111 ss_gen_pool
=(struct ss_gen
*) malloc(ss_gen_num
*
112 sizeof(struct ss_gen
));
114 memset(ss_gen_pool
, '\0',
115 ss_gen_num
* sizeof(struct ss_gen
));
117 /* enqueue all into the free generator queue */
118 for(n
=0;n
< ss_gen_num
;n
++)
119 ss_gen_enqueue(&ss_gen_free_queue
, &ss_gen_pool
[n
]);
122 if((g
=ss_gen_pop(&ss_gen_free_queue
)) != NULL
)
123 ss_gen_enqueue(q
, g
);
130 * ss_gen_free - Dequeues a generator and frees it
131 * @q: the queue holding the generator
134 * Dequeues a generator and sends it back to the generator pool.
136 void ss_gen_free(struct ss_gen
** q
, struct ss_gen
* g
)
138 ss_gen_enqueue(&ss_gen_free_queue
, ss_gen_dequeue(q
, g
));
143 * ss_gen_sustain - Sets sustain for a generator
145 * @sustain: sustain time in msecs
147 * Sets sustain for a generator, where @sustain is expressed
150 void ss_gen_sustain(struct ss_gen
* g
, double sustain
)
152 g
->sustain
=MS2F(sustain
);
157 * ss_gen_vibrato - Sets vibrato for a generator
159 * @depth: vibrato depth in msecs
160 * @freq: vibrato frequency
162 * Sets vibrato for a generator, with a @depth expressed in
163 * milliseconds and a frequency @freq expressed in hzs.
165 void ss_gen_vibrato(struct ss_gen
* g
, double depth
, double freq
)
167 /* good freq: 6 Hz (0.001) */
168 /* good depth: 1/6 semitone (20, 30 frames) */
170 g
->vib_depth
=MS2F(depth
);
171 g
->vib_inc
=( 6.28 * freq
) / (double)ss_frequency
;
177 * ss_gen_play - Activates a generator.
179 * @freq: frequency of the sound to be generated
184 * Activates a generator, usually as a response for a 'note on'
185 * message from an upper level. The wave @w holds all the sample
186 * data (PCM data, base frequency, etc.), @freq is the desired
187 * frequency, @vol the volume and @note_id a positive, unique
188 * identifier for the note.
190 void ss_gen_play(struct ss_gen
* g
, double freq
, float vol
, int note_id
,
197 memcpy(&g
->w
, w
, sizeof(struct ss_wave
));
199 /* start from the beginning */
202 /* calculate increment */
203 g
->inc
=freq
/ w
->base_freq
;
204 g
->inc
*= (double) w
->s_rate
/ (double) ss_frequency
;
206 /* default sustain, vibrato and portamento */
207 ss_gen_sustain(g
, 50.0);
208 ss_gen_vibrato(g
, 0.0, 0.0);
214 * ss_gen_release - Releases a generator.
217 * Releases a generator, usually as a response for a 'note off'
218 * message from an upper level. The generator enters SS_GEN_RELEASED
219 * mode, which starts generating sustain data until it's over.
221 void ss_gen_release(struct ss_gen
* g
)
223 /* note needs not be tracked anymore */
226 /* calculates the delta volume */
227 g
->dvol
=g
->vol
/ (float) g
->sustain
;
232 * ss_gen_frame - Generates a frame of samples.
234 * @frame: array where the output samples will be stored
236 * Generates a frame of samples from the @g generator, that will be stored
237 * in the @frame array.
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
[])
246 float l_frame
[SS_MAX_CHANNELS
];
252 /* process vibrato */
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 */
270 /* test loop boundaries */
271 if(g
->cursor
> w
->loop_end
)
274 if(w
->loop_start
< 0)
277 g
->cursor
=w
->loop_start
;
280 /* process sustain */
285 if(--g
->sustain
<= 0)
289 /* process portamento */
290 g
->inc
+= g
->portamento
;