input.c changed to ss_input.c (Closes: #1028).
[ahxm.git] / ss_gen.c
blob20712c68613ea4b9d4eceee723a4dacbc9472dcb
1 /*
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
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
33 #include "core.h"
34 #include "ss_gen.h"
36 /*******************
37 Data
38 ********************/
40 /* number of generators */
41 int _ss_gen_num=SS_GEN_NUM;
43 /* generator pool */
44 struct ss_gen * _ss_gen_pool=NULL;
46 /* free generator queue */
47 struct ss_gen * _ss_gen_free=NULL;
50 /*******************
51 Code
52 ********************/
54 void ss_gen_enqueue(struct ss_gen ** q, struct ss_gen * g)
56 g->prev=NULL;
57 g->next=*q;
59 if(*q != NULL)
60 (*q)->prev=g;
62 *q=g;
66 void ss_gen_dequeue(struct ss_gen ** q, struct ss_gen * g)
68 if(g->prev != NULL)
69 g->prev->next=g->next;
70 else
71 *q=g->next;
73 if(g->next != NULL)
74 g->next->prev=g->prev;
78 struct ss_gen * ss_gen_dequeue_first(struct ss_gen ** q)
80 struct ss_gen * g=NULL;
82 if(*q != NULL)
84 g=*q;
85 ss_gen_dequeue(q, g);
88 return(g);
92 struct ss_gen * _ss_gen_get_free(void)
94 int n;
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));
114 void ss_gen_sustain(struct ss_gen * g, double sustain)
116 g->sustain=MS2F(sustain);
120 void ss_gen_vibrato(struct ss_gen * g, double depth, double freq)
122 g->vib_depth=MS2F(depth);
123 g->vib_inc=( 6.28 * freq ) / (double)_frequency;
124 g->vibrato=0.0;
129 * ss_gen_play - Activates a generator.
130 * @note_id: note id
131 * @trk_id: track id
132 * @wave: wave samples for each channel
133 * @vol: volume for each channel
134 * @size: size of each wave in samples
135 * @inc: cursor increment (frequency)
136 * @loop_start: sample number of the start of the loop (-1, no loop)
137 * @loop_end: sample number of the end of the loop
138 * @sustain: number of samples the sound will fade out after release
140 * Activates a generator, usually as a response for a 'note on'
141 * message from an upper level. @wave sould contain pointers to PCM wave
142 * data. @inc is the cursor increment, and should be the result of the
143 * original wave's sample rate divided by the desired frequency.
144 * @loop_start and @loop_end should mark the start and end of
145 * a loop in the sound. If @loop_start is -1 and the sound cursor
146 * reaches the end of the sample, the generator stops automatically.
147 * if a loop is defined, the generator produces sound indefinitely until a
148 * call to ss_gen_release() is done.
150 * This function returns -1 if the pool went out of generators, or
151 * 0 if everything is OK and the generator entered GEN_MODE_PLAYING mode.
153 int ss_gen_play(struct ss_gen * g, int note_id, double freq, float vol[],
154 struct ss_wave * w)
156 int n;
158 g->mode=SS_GEN_PLAYING;
159 g->note_id=note_id;
161 memcpy(&g->w, w, sizeof(struct ss_wave));
163 /* transfer volumes */
164 for(n=0;n < CHANNELS;n++)
165 g->vol[n]=vol[n];
167 /* calculate increment */
168 g->inc=freq / w->base_freq;
169 g->inc *= (double) w->s_rate / (double) _frequency;
171 /* default sustain (short) */
172 ss_gen_sustain(g, 50.0);
174 /* default vibrato (none) */
175 ss_gen_vibrato(g, 0.0, 0.0);
177 /* no portamento by default */
178 g->portamento=0;
180 /* start from the beginning */
181 g->cursor=0;
183 /* TEST: vibrato */
184 /* good freq: 6 Hz */
185 /* good depth: 1/6 semitone */
186 #if 0
187 if(trk_id == 2)
189 g->vib_depth=30; /* 20 */
190 g->vib_inc=( 6.28 * 6.0 ) / (double)_frequency; /* 0.001 */
192 else
193 g->vib_inc=0.0;
194 #endif
196 return(0);
201 * ss_gen_release - Releases generators.
202 * @note_id: note id
204 * Releases the generators associated to @note_id, usually as a response
205 * for a 'note off' message from an upper level. The generator enters
206 * GEN_MODE_RELEASED mode.
208 * Returns the number of released generators.
210 int ss_gen_release(struct ss_gen * g)
212 int n;
214 /* note needs not be tracked anymore */
215 g->note_id=-1;
217 /* generator is released */
218 g->mode=SS_GEN_RELEASED;
220 /* calculates delta volume values */
221 for(n=0;n < CHANNELS;n++)
223 if(g->w.wave[n])
224 g->dvol[n]=g->vol[n] / (float) g->sustain;
225 else
226 g->dvol[n]=0.0;
229 return(1);
234 * ss_gen_frame - Generates a frame of samples.
235 * @trk_id: track id
236 * @frame: array where the output samples will be stored
238 * Generates a frame of samples for the track @trk_id, that will be stored
239 * in the @sample array. If the generator is in GEN_MODE_RELEASED mode,
240 * the sound should keep fading-out until the sustain time is exhausted and
241 * then moved to GEN_MODE_FREE mode; if the generator is playing and
242 * a non-looped sound reaches the end, it's immediately stopped.
243 * It also processes portamento.
245 int ss_gen_frame(struct ss_gen * g, float frame[])
247 float s;
248 int n;
249 int to_free=0;
250 double v;
252 /* process vibrato */
253 if(g->vib_inc)
255 g->vibrato += g->vib_inc;
256 v=sin(g->vibrato) * g->vib_depth;
258 else
259 v=0.0;
261 /* get samples */
262 for(n=0;n < CHANNELS;n++)
264 if(g->w.wave[n] != NULL)
266 s=get_sample(&g->w, n, g->cursor + v);
267 s *= g->vol[n];
269 frame[n] += s;
273 /* increment pointer */
274 g->cursor += g->inc;
276 /* test loop boundaries */
277 if(g->cursor > g->w.loop_end)
279 /* loop mode? */
280 if(g->w.loop_start == -1)
281 to_free=1;
282 else
283 g->cursor=g->w.loop_start;
286 /* process sustain */
287 if(g->mode == SS_GEN_RELEASED)
289 for(n=0;n < CHANNELS;n++)
290 g->vol[n] -= g->dvol[n];
292 if(--g->sustain <= 0)
293 to_free=1;
296 /* process portamento */
297 g->inc += g->portamento;
299 return(to_free);
304 * ss_gen_portamento - Sets portamento for a generator.
305 * @g: the generator
306 * @portamento: portamento time
307 * @dest_inc: destination inc (frequency)
309 * Sets the portamento for a generator. @portamento is the
310 * number of frames the generator should move from its current
311 * cursor increment to @dest_inc. See generator_play() for an
312 * explanation of the value contained in @dest_inc.
314 * Returns -1 if the generator is not active, or 0 if the
315 * portamento was accepted.
317 * FIXME: The API for portamento will surely change.
319 int ss_gen_portamento(struct ss_gen * g, int portamento, double dest_inc)
321 /* generator must be playing */
322 if(g->mode != SS_GEN_PLAYING)
323 return(-1);
325 g->portamento=portamento;
326 g->dest_inc=dest_inc;
327 g->dinc=((dest_inc - g->inc) / (double) portamento);
329 return(0);