mp3: fix error handling in rewrite_tags()
[sox.git] / src / chorus.c
blob96ca9df86d6cd1af3d8db120a90085e3010f8ee2
1 /* August 24, 1998
2 * Copyright (C) 1998 Juergen Mueller And Sundry Contributors
3 * This source code is freely redistributable and may be used for
4 * any purpose. This copyright notice must be maintained.
5 * Juergen Mueller And Sundry Contributors are not responsible for
6 * the consequences of using this software.
7 */
9 /*
10 * Chorus effect.
12 * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
14 * * gain-in ___
15 * ibuff -----+--------------------------------------------->| |
16 * | _________ | |
17 * | | | * decay 1 | |
18 * +---->| delay 1 |----------------------------->| |
19 * | |_________| | |
20 * | /|\ | |
21 * : | | |
22 * : +-----------------+ +--------------+ | + |
23 * : | Delay control 1 |<--| mod. speed 1 | | |
24 * : +-----------------+ +--------------+ | |
25 * | _________ | |
26 * | | | * decay n | |
27 * +---->| delay n |----------------------------->| |
28 * |_________| | |
29 * /|\ |___|
30 * | |
31 * +-----------------+ +--------------+ | * gain-out
32 * | Delay control n |<--| mod. speed n | |
33 * +-----------------+ +--------------+ +----->obuff
36 * The delay i is controled by a sine or triangle modulation i ( 1 <= i <= n).
38 * Usage:
39 * chorus gain-in gain-out delay-1 decay-1 speed-1 depth-1 -s1|t1 [
40 * delay-2 decay-2 speed-2 depth-2 -s2|-t2 ... ]
42 * Where:
43 * gain-in, decay-1 ... decay-n : 0.0 ... 1.0 volume
44 * gain-out : 0.0 ... volume
45 * delay-1 ... delay-n : 20.0 ... 100.0 msec
46 * speed-1 ... speed-n : 0.1 ... 5.0 Hz modulation 1 ... n
47 * depth-1 ... depth-n : 0.0 ... 10.0 msec modulated delay 1 ... n
48 * -s1 ... -sn : modulation by sine 1 ... n
49 * -t1 ... -tn : modulation by triangle 1 ... n
51 * Note:
52 * when decay is close to 1.0, the samples can begin clipping and the output
53 * can saturate!
55 * Hint:
56 * 1 / out-gain < gain-in ( 1 + decay-1 + ... + decay-n )
61 * libSoX chorus effect file.
64 #include "sox_i.h"
66 #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
67 #include <string.h>
69 #define MOD_SINE 0
70 #define MOD_TRIANGLE 1
71 #define MAX_CHORUS 7
73 typedef struct {
74 int num_chorus;
75 int modulation[MAX_CHORUS];
76 int counter;
77 long phase[MAX_CHORUS];
78 float *chorusbuf;
79 float in_gain, out_gain;
80 float delay[MAX_CHORUS], decay[MAX_CHORUS];
81 float speed[MAX_CHORUS], depth[MAX_CHORUS];
82 long length[MAX_CHORUS];
83 int *lookup_tab[MAX_CHORUS];
84 int depth_samples[MAX_CHORUS], samples[MAX_CHORUS];
85 int maxsamples;
86 unsigned int fade_out;
87 } priv_t;
90 * Process options
92 static int sox_chorus_getopts(sox_effect_t * effp, int argc, char **argv)
94 priv_t * chorus = (priv_t *) effp->priv;
95 int i;
96 --argc, ++argv;
98 chorus->num_chorus = 0;
99 i = 0;
101 if ( ( argc < 7 ) || (( argc - 2 ) % 5 ) )
102 return lsx_usage(effp);
104 sscanf(argv[i++], "%f", &chorus->in_gain);
105 sscanf(argv[i++], "%f", &chorus->out_gain);
106 while ( i < argc ) {
107 if ( chorus->num_chorus > MAX_CHORUS )
109 lsx_fail("chorus: to many delays, use less than %i delays", MAX_CHORUS);
110 return (SOX_EOF);
112 sscanf(argv[i++], "%f", &chorus->delay[chorus->num_chorus]);
113 sscanf(argv[i++], "%f", &chorus->decay[chorus->num_chorus]);
114 sscanf(argv[i++], "%f", &chorus->speed[chorus->num_chorus]);
115 sscanf(argv[i++], "%f", &chorus->depth[chorus->num_chorus]);
116 if ( !strcmp(argv[i], "-s"))
117 chorus->modulation[chorus->num_chorus] = MOD_SINE;
118 else if ( ! strcmp(argv[i], "-t"))
119 chorus->modulation[chorus->num_chorus] = MOD_TRIANGLE;
120 else
121 return lsx_usage(effp);
122 i++;
123 chorus->num_chorus++;
125 return (SOX_SUCCESS);
129 * Prepare for processing.
131 static int sox_chorus_start(sox_effect_t * effp)
133 priv_t * chorus = (priv_t *) effp->priv;
134 int i;
135 float sum_in_volume;
137 chorus->maxsamples = 0;
139 if ( chorus->in_gain < 0.0 )
141 lsx_fail("chorus: gain-in must be positive!");
142 return (SOX_EOF);
144 if ( chorus->in_gain > 1.0 )
146 lsx_fail("chorus: gain-in must be less than 1.0!");
147 return (SOX_EOF);
149 if ( chorus->out_gain < 0.0 )
151 lsx_fail("chorus: gain-out must be positive!");
152 return (SOX_EOF);
154 for ( i = 0; i < chorus->num_chorus; i++ ) {
155 chorus->samples[i] = (int) ( ( chorus->delay[i] +
156 chorus->depth[i] ) * effp->in_signal.rate / 1000.0);
157 chorus->depth_samples[i] = (int) (chorus->depth[i] *
158 effp->in_signal.rate / 1000.0);
160 if ( chorus->delay[i] < 20.0 )
162 lsx_fail("chorus: delay must be more than 20.0 msec!");
163 return (SOX_EOF);
165 if ( chorus->delay[i] > 100.0 )
167 lsx_fail("chorus: delay must be less than 100.0 msec!");
168 return (SOX_EOF);
170 if ( chorus->speed[i] < 0.1 )
172 lsx_fail("chorus: speed must be more than 0.1 Hz!");
173 return (SOX_EOF);
175 if ( chorus->speed[i] > 5.0 )
177 lsx_fail("chorus: speed must be less than 5.0 Hz!");
178 return (SOX_EOF);
180 if ( chorus->depth[i] < 0.0 )
182 lsx_fail("chorus: delay must be more positive!");
183 return (SOX_EOF);
185 if ( chorus->depth[i] > 10.0 )
187 lsx_fail("chorus: delay must be less than 10.0 msec!");
188 return (SOX_EOF);
190 if ( chorus->decay[i] < 0.0 )
192 lsx_fail("chorus: decay must be positive!" );
193 return (SOX_EOF);
195 if ( chorus->decay[i] > 1.0 )
197 lsx_fail("chorus: decay must be less that 1.0!" );
198 return (SOX_EOF);
200 chorus->length[i] = effp->in_signal.rate / chorus->speed[i];
201 chorus->lookup_tab[i] = lsx_malloc(sizeof (int) * chorus->length[i]);
203 if (chorus->modulation[i] == MOD_SINE)
204 lsx_generate_wave_table(SOX_WAVE_SINE, SOX_INT, chorus->lookup_tab[i],
205 (size_t)chorus->length[i], 0., (double)chorus->depth_samples[i], 0.);
206 else
207 lsx_generate_wave_table(SOX_WAVE_TRIANGLE, SOX_INT, chorus->lookup_tab[i],
208 (size_t)chorus->length[i],
209 (double)(chorus->samples[i] - 1 - 2 * chorus->depth_samples[i]),
210 (double)(chorus->samples[i] - 1), 3 * M_PI_2);
211 chorus->phase[i] = 0;
213 if ( chorus->samples[i] > chorus->maxsamples )
214 chorus->maxsamples = chorus->samples[i];
217 /* Be nice and check the hint with warning, if... */
218 sum_in_volume = 1.0;
219 for ( i = 0; i < chorus->num_chorus; i++ )
220 sum_in_volume += chorus->decay[i];
221 if ( chorus->in_gain * ( sum_in_volume ) > 1.0 / chorus->out_gain )
222 lsx_warn("chorus: warning >>> gain-out can cause saturation or clipping of output <<<");
225 chorus->chorusbuf = lsx_malloc(sizeof (float) * chorus->maxsamples);
226 for ( i = 0; i < chorus->maxsamples; i++ )
227 chorus->chorusbuf[i] = 0.0;
229 chorus->counter = 0;
230 chorus->fade_out = chorus->maxsamples;
232 effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
234 return (SOX_SUCCESS);
238 * Processed signed long samples from ibuf to obuf.
239 * Return number of samples processed.
241 static int sox_chorus_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
242 size_t *isamp, size_t *osamp)
244 priv_t * chorus = (priv_t *) effp->priv;
245 int i;
246 float d_in, d_out;
247 sox_sample_t out;
248 size_t len = min(*isamp, *osamp);
249 *isamp = *osamp = len;
251 while (len--) {
252 /* Store delays as 24-bit signed longs */
253 d_in = (float) *ibuf++ / 256;
254 /* Compute output first */
255 d_out = d_in * chorus->in_gain;
256 for ( i = 0; i < chorus->num_chorus; i++ )
257 d_out += chorus->chorusbuf[(chorus->maxsamples +
258 chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) %
259 chorus->maxsamples] * chorus->decay[i];
260 /* Adjust the output volume and size to 24 bit */
261 d_out = d_out * chorus->out_gain;
262 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
263 *obuf++ = out * 256;
264 /* Mix decay of delay and input */
265 chorus->chorusbuf[chorus->counter] = d_in;
266 chorus->counter =
267 ( chorus->counter + 1 ) % chorus->maxsamples;
268 for ( i = 0; i < chorus->num_chorus; i++ )
269 chorus->phase[i] =
270 ( chorus->phase[i] + 1 ) % chorus->length[i];
272 /* processed all samples */
273 return (SOX_SUCCESS);
277 * Drain out reverb lines.
279 static int sox_chorus_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
281 priv_t * chorus = (priv_t *) effp->priv;
282 size_t done;
283 int i;
285 float d_in, d_out;
286 sox_sample_t out;
288 done = 0;
289 while ( ( done < *osamp ) && ( done < chorus->fade_out ) ) {
290 d_in = 0;
291 d_out = 0;
292 /* Compute output first */
293 for ( i = 0; i < chorus->num_chorus; i++ )
294 d_out += chorus->chorusbuf[(chorus->maxsamples +
295 chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) %
296 chorus->maxsamples] * chorus->decay[i];
297 /* Adjust the output volume and size to 24 bit */
298 d_out = d_out * chorus->out_gain;
299 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
300 *obuf++ = out * 256;
301 /* Mix decay of delay and input */
302 chorus->chorusbuf[chorus->counter] = d_in;
303 chorus->counter =
304 ( chorus->counter + 1 ) % chorus->maxsamples;
305 for ( i = 0; i < chorus->num_chorus; i++ )
306 chorus->phase[i] =
307 ( chorus->phase[i] + 1 ) % chorus->length[i];
308 done++;
309 chorus->fade_out--;
311 /* samples played, it remains */
312 *osamp = done;
313 if (chorus->fade_out == 0)
314 return SOX_EOF;
315 else
316 return SOX_SUCCESS;
320 * Clean up chorus effect.
322 static int sox_chorus_stop(sox_effect_t * effp)
324 priv_t * chorus = (priv_t *) effp->priv;
325 int i;
327 free(chorus->chorusbuf);
328 chorus->chorusbuf = NULL;
329 for ( i = 0; i < chorus->num_chorus; i++ ) {
330 free(chorus->lookup_tab[i]);
331 chorus->lookup_tab[i] = NULL;
333 return (SOX_SUCCESS);
336 static sox_effect_handler_t sox_chorus_effect = {
337 "chorus",
338 "gain-in gain-out delay decay speed depth [ -s | -t ]",
339 SOX_EFF_LENGTH | SOX_EFF_GAIN,
340 sox_chorus_getopts,
341 sox_chorus_start,
342 sox_chorus_flow,
343 sox_chorus_drain,
344 sox_chorus_stop,
345 NULL, sizeof(priv_t)
348 const sox_effect_handler_t *lsx_chorus_effect_fn(void)
350 return &sox_chorus_effect;