3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2004 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 struct ss_gen
* _ss_gen_pool
=NULL
;
46 /* free generator queue */
47 struct ss_gen
* _ss_gen_free
=NULL
;
54 void ss_gen_enqueue(struct ss_gen
** q
, struct ss_gen
* g
)
66 void ss_gen_dequeue(struct ss_gen
** q
, struct ss_gen
* g
)
69 g
->prev
->next
=g
->next
;
74 g
->next
->prev
=g
->prev
;
78 struct ss_gen
* ss_gen_dequeue_first(struct ss_gen
** q
)
80 struct ss_gen
* g
=NULL
;
92 struct ss_gen
* _ss_gen_get_free(void)
96 /* first time allocation */
97 if(_ss_gen_pool
== NULL
)
99 _ss_gen_pool
=(struct ss_gen
*) malloc(_ss_gen_num
*
100 sizeof(struct ss_gen
));
102 memset(_ss_gen_pool
, '\0',
103 _ss_gen_num
* sizeof(struct ss_gen
));
105 /* enqueue all into the free generator queue */
106 for(n
=0;n
< _ss_gen_num
;n
++)
107 ss_gen_enqueue(&_ss_gen_free
, &_ss_gen_pool
[n
]);
110 return(ss_gen_dequeue_first(&_ss_gen_free
));
115 * ss_gen_play - Activates a generator.
118 * @wave: wave samples for each channel
119 * @vol: volume for each channel
120 * @size: size of each wave in samples
121 * @inc: cursor increment (frequency)
122 * @loop_start: sample number of the start of the loop (-1, no loop)
123 * @loop_end: sample number of the end of the loop
124 * @sustain: number of samples the sound will fade out after release
126 * Activates a generator, usually as a response for a 'note on'
127 * message from an upper level. @wave sould contain pointers to PCM wave
128 * data. @inc is the cursor increment, and should be the result of the
129 * original wave's sample rate divided by the desired frequency.
130 * @loop_start and @loop_end should mark the start and end of
131 * a loop in the sound. If @loop_start is -1 and the sound cursor
132 * reaches the end of the sample, the generator stops automatically.
133 * if a loop is defined, the generator produces sound indefinitely until a
134 * call to ss_gen_release() is done.
136 * This function returns -1 if the pool went out of generators, or
137 * 0 if everything is OK and the generator entered GEN_MODE_PLAYING mode.
139 int ss_gen_play(struct ss_gen
* g
, int note_id
, double freq
, float vol
[],
144 g
->mode
=SS_GEN_PLAYING
;
147 memcpy(&g
->w
, w
, sizeof(struct ss_wave
));
149 /* transfer volumes */
150 for(n
=0;n
< CHANNELS
;n
++)
153 /* calculate increment */
154 g
->inc
=freq
/ w
->base_freq
;
155 g
->inc
*= (double) w
->s_rate
/ (double) _frequency
;
157 /* g->sustain=sustain; */
158 g
->sustain
=_frequency
/ 100;
160 /* no portamento by default */
163 /* start from the beginning */
169 /* good freq: 6 Hz */
170 /* good depth: 1/6 semitone */
174 g
->vib_depth
=30; /* 20 */
175 g
->vib_inc
=( 6.28 * 6.0 ) / (double)_frequency
; /* 0.001 */
186 * ss_gen_release - Releases generators.
189 * Releases the generators associated to @note_id, usually as a response
190 * for a 'note off' message from an upper level. The generator enters
191 * GEN_MODE_RELEASED mode.
193 * Returns the number of released generators.
195 int ss_gen_release(struct ss_gen
* g
)
199 /* note needs not be tracked anymore */
202 /* generator is released */
203 g
->mode
=SS_GEN_RELEASED
;
205 /* calculates delta volume values */
206 for(n
=0;n
< CHANNELS
;n
++)
209 g
->dvol
[n
]=g
->vol
[n
] / (float) g
->sustain
;
219 * ss_gen_frame - Generates a frame of samples.
221 * @frame: array where the output samples will be stored
223 * Generates a frame of samples for the track @trk_id, that will be stored
224 * in the @sample array. If the generator is in GEN_MODE_RELEASED mode,
225 * the sound should keep fading-out until the sustain time is exhausted and
226 * then moved to GEN_MODE_FREE mode; if the generator is playing and
227 * a non-looped sound reaches the end, it's immediately stopped.
228 * It also processes portamento.
230 int ss_gen_frame(struct ss_gen
* g
, float frame
[])
237 /* process vibrato */
240 g
->vibrato
+= g
->vib_inc
;
241 v
=sin(g
->vibrato
) * g
->vib_depth
;
247 for(n
=0;n
< CHANNELS
;n
++)
249 if(g
->w
.wave
[n
] != NULL
)
251 s
=get_sample(&g
->w
, n
, g
->cursor
+ v
);
258 /* increment pointer */
261 /* test loop boundaries */
262 if(g
->cursor
> g
->w
.loop_end
)
265 if(g
->w
.loop_start
== -1)
268 g
->cursor
=g
->w
.loop_start
;
271 /* process sustain */
272 if(g
->mode
== SS_GEN_RELEASED
)
274 for(n
=0;n
< CHANNELS
;n
++)
275 g
->vol
[n
] -= g
->dvol
[n
];
277 if(--g
->sustain
<= 0)
281 /* process portamento */
282 g
->inc
+= g
->portamento
;
289 * ss_gen_portamento - Sets portamento for a generator.
291 * @portamento: portamento time
292 * @dest_inc: destination inc (frequency)
294 * Sets the portamento for a generator. @portamento is the
295 * number of frames the generator should move from its current
296 * cursor increment to @dest_inc. See generator_play() for an
297 * explanation of the value contained in @dest_inc.
299 * Returns -1 if the generator is not active, or 0 if the
300 * portamento was accepted.
302 * FIXME: The API for portamento will surely change.
304 int ss_gen_portamento(struct ss_gen
* g
, int portamento
, double dest_inc
)
306 /* generator must be playing */
307 if(g
->mode
!= SS_GEN_PLAYING
)
310 g->portamento=portamento;
311 g->dest_inc=dest_inc;
312 g->dinc=((dest_inc - g->inc) / (double) portamento);
318 void ss_gen_vibrato(struct ss_gen
* g
, double depth
, double freq
)
321 g
->vib_inc
=( 6.28 * freq
) / (double)_frequency
;