Fixed a cosmetic bug in _add_measure_event().
[ahxm.git] / ss_gen.c
blobcbbe9d265edafeba7969c9da9400b535b2b254fd
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;
47 /*******************
48 Code
49 ********************/
51 struct ss_gen * _ss_gen_get_free(void)
53 int n;
55 /* first time allocation */
56 if(_ss_gen_pool == NULL)
58 _ss_gen_pool=(struct ss_gen *) malloc(_ss_gen_num *
59 sizeof(struct ss_gen));
61 memset(_ss_gen_pool, '\0', _ss_gen_num * sizeof(struct ss_gen));
64 /* find one in SS_GEN_FREE mode */
65 for(n=0;n < _ss_gen_num;n++)
67 if(_ss_gen_pool[n].mode == SS_GEN_FREE)
68 return(&_ss_gen_pool[n]);
71 return(NULL);
75 /**
76 * ss_gen_play - Activates a generator.
77 * @note_id: note id
78 * @trk_id: track id
79 * @wave: wave samples for each channel
80 * @vol: volume for each channel
81 * @size: size of each wave in samples
82 * @inc: cursor increment (frequency)
83 * @loop_start: sample number of the start of the loop (-1, no loop)
84 * @loop_end: sample number of the end of the loop
85 * @sustain: number of samples the sound will fade out after release
87 * Activates a generator, usually as a response for a 'note on'
88 * message from an upper level. @wave sould contain pointers to PCM wave
89 * data. @inc is the cursor increment, and should be the result of the
90 * original wave's sample rate divided by the desired frequency.
91 * @loop_start and @loop_end should mark the start and end of
92 * a loop in the sound. If @loop_start is -1 and the sound cursor
93 * reaches the end of the sample, the generator stops automatically.
94 * if a loop is defined, the generator produces sound indefinitely until a
95 * call to ss_gen_release() is done.
97 * This function returns -1 if the pool went out of generators, or
98 * 0 if everything is OK and the generator entered GEN_MODE_PLAYING mode.
100 int ss_gen_play(int note_id, int trk_id, double freq, float vol[],
101 struct ss_wave * w)
103 struct ss_gen * g;
104 int n;
106 /* find a free generator or fail */
107 if((g=_ss_gen_get_free()) == NULL)
108 return(-1);
110 g->mode=SS_GEN_PLAYING;
111 g->note_id=note_id;
112 g->trk_id=trk_id;
114 memcpy(&g->w, w, sizeof(struct ss_wave));
116 /* transfer volumes */
117 for(n=0;n < CHANNELS;n++)
118 g->vol[n]=vol[n];
120 /* calculate increment */
121 g->inc=freq / w->base_freq;
122 g->inc *= (double) w->s_rate / (double) _frequency;
124 /* g->sustain=sustain; */
125 g->sustain=_frequency / 100;
127 /* no portamento by default */
128 g->portamento=0;
130 /* start from the beginning */
131 g->cursor=0;
133 g->vibrato=0;
135 /* TEST: vibrato */
136 /* good freq: 6 Hz */
137 /* good depth: 1/6 semitone */
138 if(trk_id == 2)
140 g->vib_depth=30; /* 20 */
141 g->vib_inc=( 6.28 * 6.0 ) / (double)_frequency; /* 0.001 */
143 else
144 g->vib_inc=0.0;
146 return(0);
151 * ss_gen_release - Releases generators.
152 * @note_id: note id
154 * Releases the generators associated to @note_id, usually as a response
155 * for a 'note off' message from an upper level. The generator enters
156 * GEN_MODE_RELEASED mode.
158 * Returns the number of released generators.
160 int ss_gen_release(int note_id)
162 struct ss_gen * g;
163 int n, m;
164 int notes=0;
166 for(n=0;n < _ss_gen_num;n++)
168 g=&_ss_gen_pool[n];
170 if(g->note_id != note_id)
171 continue;
173 /* note needs not be tracked anymore */
174 g->note_id=-1;
176 /* generator is released */
177 g->mode=SS_GEN_RELEASED;
179 /* calculates delta volume values */
180 for(m=0;m < CHANNELS;m++)
182 if(g->w.wave[m])
183 g->dvol[m]=g->vol[m] / (float) g->sustain;
184 else
185 g->dvol[m]=0.0;
188 notes++;
191 return(notes);
195 int _ss_gen_frame(struct ss_gen * g, float frame[])
197 float s;
198 int n;
199 int to_free=0;
200 double v;
202 /* return if generator is not active */
203 if(g->mode == SS_GEN_FREE)
204 return(0);
206 /* process vibrato */
207 if(g->vib_inc)
209 g->vibrato += g->vib_inc;
210 v=sin(g->vibrato) * g->vib_depth;
212 else
213 v=0.0;
215 /* get samples */
216 for(n=0;n < CHANNELS;n++)
218 if(g->w.wave[n] != NULL)
220 s=get_sample(&g->w, n, g->cursor + v);
221 s *= g->vol[n];
223 frame[n] += s;
227 /* increment pointer */
228 g->cursor += g->inc;
230 /* test loop boundaries */
231 if(g->cursor > g->w.loop_end)
233 /* loop mode? */
234 if(g->w.loop_start == -1)
235 to_free=1;
236 else
237 g->cursor=g->w.loop_start;
240 /* process sustain */
241 if(g->mode == SS_GEN_RELEASED)
243 for(n=0;n < CHANNELS;n++)
244 g->vol[n] -= g->dvol[n];
246 if(--g->sustain <= 0)
247 to_free=1;
250 /* process portamento */
251 if(g->portamento)
253 if(--g->portamento <= 0)
254 g->inc=g->dest_inc;
255 else
256 g->inc += g->dinc;
259 if(to_free)
260 g->mode=SS_GEN_FREE;
262 return(1);
267 * ss_gen_frame - Generates a frame of samples.
268 * @trk_id: track id
269 * @frame: array where the output samples will be stored
271 * Generates a frame of samples for the track @trk_id, that will be stored
272 * in the @sample array. If the generator is in GEN_MODE_RELEASED mode,
273 * the sound should keep fading-out until the sustain time is exhausted and
274 * then moved to GEN_MODE_FREE mode; if the generator is playing and
275 * a non-looped sound reaches the end, it's immediately stopped.
276 * It also processes portamento.
278 void ss_gen_frame(int trk_id, float frame[])
280 struct ss_gen * g;
281 int n;
283 for(n=0;n < _ss_gen_num;n++)
285 g=&_ss_gen_pool[n];
287 if(g->trk_id == trk_id)
288 _ss_gen_frame(g, frame);
294 * ss_gen_portamento - Sets portamento for a generator.
295 * @g: the generator
296 * @portamento: portamento time
297 * @dest_inc: destination inc (frequency)
299 * Sets the portamento for a generator. @portamento is the
300 * number of frames the generator should move from its current
301 * cursor increment to @dest_inc. See generator_play() for an
302 * explanation of the value contained in @dest_inc.
304 * Returns -1 if the generator is not active, or 0 if the
305 * portamento was accepted.
307 * FIXME: The API for portamento will surely change.
309 int ss_gen_portamento(struct ss_gen * g, int portamento, double dest_inc)
311 /* generator must be playing */
312 if(g->mode != SS_GEN_PLAYING)
313 return(-1);
315 g->portamento=portamento;
316 g->dest_inc=dest_inc;
317 g->dinc=((dest_inc - g->inc) / (double) portamento);
319 return(0);
323 void ss_gen_vibrato(struct ss_gen * g, double depth, double freq)
325 g->vib_depth=depth;
326 g->vib_inc=( 6.28 * freq ) / (double)_frequency;