1 /*
2 * August 24, 1998
3 * Copyright (C) 1998 Juergen Mueller And Sundry Contributors
4 * This source code is freely redistributable and may be used for
5 * any purpose. This copyright notice must be maintained.
6 * Juergen Mueller And Sundry Contributors are not responsible for
7 * the consequences of using this software.
8 */
9
10 /*
11
12 CHANGES
13
14 - Adapted for fluidsynth, Peter Hanappe, March 2002
15
16 - Variable delay line implementation using bandlimited
17 interpolation, code reorganization: Markus Nentwig May 2002
18
19 */
20
21
22 /*
23 * Chorus effect.
24 *
25 * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
26 *
27 * * gain-in ___
28 * ibuff -----+--------------------------------------------->| |
29 * | _________ | |
30 * | | | * level 1 | |
31 * +---->| delay 1 |----------------------------->| |
32 * | |_________| | |
33 * | /|\ | |
34 * : | | |
35 * : +-----------------+ +--------------+ | + |
36 * : | Delay control 1 |<--| mod. speed 1 | | |
37 * : +-----------------+ +--------------+ | |
38 * | _________ | |
39 * | | | * level n | |
40 * +---->| delay n |----------------------------->| |
41 * |_________| | |
42 * /|\ |___|
43 * | |
44 * +-----------------+ +--------------+ | * gain-out
45 * | Delay control n |<--| mod. speed n | |
46 * +-----------------+ +--------------+ +----->obuff
47 *
48 *
49 * The delay i is controlled by a sine or triangle modulation i ( 1 <= i <= n).
50 *
51 * The delay of each block is modulated between 0..depth ms
52 *
53 */
54
55
56 /* Variable delay line implementation
57 * ==================================
58 *
59 * The modulated delay needs the value of the delayed signal between
60 * samples. A lowpass filter is used to obtain intermediate values
61 * between samples (bandlimited interpolation). The sample pulse
62 * train is convoluted with the impulse response of the low pass
63 * filter (sinc function). To make it work with a small number of
64 * samples, the sinc function is windowed (Hamming window).
65 *
66 */
67
68 #include "fluid_chorus.h"
69 #include "fluid_sys.h"
70
71 #define MAX_CHORUS 99
72 #define MAX_DELAY 100
73 #define MAX_DEPTH 10
74 #define MIN_SPEED_HZ 0.29
75 #define MAX_SPEED_HZ 5
76
77 /* Length of one delay line in samples:
78 * Set through MAX_SAMPLES_LN2.
79 * For example:
80 * MAX_SAMPLES_LN2=12
81 * => MAX_SAMPLES=pow(2,12)=4096
82 * => MAX_SAMPLES_ANDMASK=4095
83 */
84 #define MAX_SAMPLES_LN2 12
85
86 #define MAX_SAMPLES (1 << (MAX_SAMPLES_LN2-1))
87 #define MAX_SAMPLES_ANDMASK (MAX_SAMPLES-1)
88
89
90 /* Interpolate how many steps between samples? Must be power of two
91 For example: 8 => use a resolution of 256 steps between any two
92 samples
93 */
94 #define INTERPOLATION_SUBSAMPLES_LN2 8
95 #define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
96 #define INTERPOLATION_SUBSAMPLES_ANDMASK (INTERPOLATION_SUBSAMPLES-1)
97
98 /* Use how many samples for interpolation? Must be odd. '7' sounds
99 relatively clean, when listening to the modulated delay signal
100 alone. For a demo on aliasing try '1' With '3', the aliasing is
101 still quite pronounced for some input frequencies
102 */
103 #define INTERPOLATION_SAMPLES 5
104
105 /* Private data for SKEL file */
106 struct _fluid_chorus_t {
107 int type;
108 fluid_real_t depth_ms;
109 fluid_real_t level;
110 fluid_real_t speed_Hz;
111 int number_blocks;
112
113 fluid_real_t *chorusbuf;
114 int counter;
115 long phase[MAX_CHORUS];
116 long modulation_period_samples;
117 int *lookup_tab;
118 fluid_real_t sample_rate;
119
120 /* sinc lookup table */
121 fluid_real_t sinc_table[INTERPOLATION_SAMPLES][INTERPOLATION_SUBSAMPLES];
122 };
123
124 static void fluid_chorus_triangle(int *buf, int len, int depth);
125 static void fluid_chorus_sine(int *buf, int len, int depth);
126
127
128 fluid_chorus_t*
new_fluid_chorus(fluid_real_t sample_rate)129 new_fluid_chorus(fluid_real_t sample_rate)
130 {
131 int i; int ii;
132 fluid_chorus_t* chorus;
133
134 chorus = FLUID_NEW(fluid_chorus_t);
135 if (chorus == NULL) {
136 fluid_log(FLUID_PANIC, "chorus: Out of memory");
137 return NULL;
138 }
139
140 FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t));
141
142 chorus->sample_rate = sample_rate;
143
144 /* Lookup table for the SI function (impulse response of an ideal low pass) */
145
146 /* i: Offset in terms of whole samples */
147 for (i = 0; i < INTERPOLATION_SAMPLES; i++){
148
149 /* ii: Offset in terms of fractional samples ('subsamples') */
150 for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
151 /* Move the origin into the center of the table */
152 double i_shifted = ((double) i- ((double) INTERPOLATION_SAMPLES) / 2.
153 + (double) ii / (double) INTERPOLATION_SUBSAMPLES);
154 if (fabs(i_shifted) < 0.000001) {
155 /* sinc(0) cannot be calculated straightforward (limit needed
156 for 0/0) */
157 chorus->sinc_table[i][ii] = (fluid_real_t)1.;
158
159 } else {
160 chorus->sinc_table[i][ii] = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted);
161 /* Hamming window */
162 chorus->sinc_table[i][ii] *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)INTERPOLATION_SAMPLES));
163 };
164 };
165 };
166
167 /* allocate lookup tables */
168 chorus->lookup_tab = FLUID_ARRAY(int, (int) (chorus->sample_rate / MIN_SPEED_HZ));
169 if (chorus->lookup_tab == NULL) {
170 fluid_log(FLUID_PANIC, "chorus: Out of memory");
171 goto error_recovery;
172 }
173
174 /* allocate sample buffer */
175
176 chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
177 if (chorus->chorusbuf == NULL) {
178 fluid_log(FLUID_PANIC, "chorus: Out of memory");
179 goto error_recovery;
180 }
181
182 if (fluid_chorus_init(chorus) != FLUID_OK){
183 goto error_recovery;
184 };
185
186 return chorus;
187
188 error_recovery:
189 delete_fluid_chorus(chorus);
190 return NULL;
191 }
192
193 void
delete_fluid_chorus(fluid_chorus_t * chorus)194 delete_fluid_chorus(fluid_chorus_t* chorus)
195 {
196 if (chorus == NULL) {
197 return;
198 }
199
200 if (chorus->chorusbuf != NULL) {
201 FLUID_FREE(chorus->chorusbuf);
202 }
203
204 if (chorus->lookup_tab != NULL) {
205 FLUID_FREE(chorus->lookup_tab);
206 }
207
208 FLUID_FREE(chorus);
209 }
210
211 int
fluid_chorus_init(fluid_chorus_t * chorus)212 fluid_chorus_init(fluid_chorus_t* chorus)
213 {
214 int i;
215
216 for (i = 0; i < MAX_SAMPLES; i++) {
217 chorus->chorusbuf[i] = 0.0;
218 }
219
220 /* initialize the chorus with the default settings */
221 fluid_chorus_set (chorus, FLUID_CHORUS_SET_ALL, FLUID_CHORUS_DEFAULT_N,
222 FLUID_CHORUS_DEFAULT_LEVEL, FLUID_CHORUS_DEFAULT_SPEED,
223 FLUID_CHORUS_DEFAULT_DEPTH, FLUID_CHORUS_MOD_SINE);
224 return FLUID_OK;
225 }
226
227 void
fluid_chorus_reset(fluid_chorus_t * chorus)228 fluid_chorus_reset(fluid_chorus_t* chorus)
229 {
230 fluid_chorus_init(chorus);
231 }
232
233 /**
234 * Set one or more chorus parameters.
235 * @param chorus Chorus instance
236 * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
237 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
238 * this value)
239 * @param level Chorus level (0.0-10.0)
240 * @param speed Chorus speed in Hz (0.29-5.0)
241 * @param depth_ms Chorus depth (max value depends on synth sample rate,
242 * 0.0-21.0 is safe for sample rate values up to 96KHz)
243 * @param type Chorus waveform type (#fluid_chorus_mod)
244 */
245 void
fluid_chorus_set(fluid_chorus_t * chorus,int set,int nr,float level,float speed,float depth_ms,int type)246 fluid_chorus_set(fluid_chorus_t* chorus, int set, int nr, float level,
247 float speed, float depth_ms, int type)
248 {
249 int modulation_depth_samples;
250 int i;
251
252 if (set & FLUID_CHORUS_SET_NR) chorus->number_blocks = nr;
253 if (set & FLUID_CHORUS_SET_LEVEL) chorus->level = level;
254 if (set & FLUID_CHORUS_SET_SPEED) chorus->speed_Hz = speed;
255 if (set & FLUID_CHORUS_SET_DEPTH) chorus->depth_ms = depth_ms;
256 if (set & FLUID_CHORUS_SET_TYPE) chorus->type = type;
257
258 if (chorus->number_blocks < 0) {
259 fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
260 chorus->number_blocks = 0;
261 } else if (chorus->number_blocks > MAX_CHORUS) {
262 fluid_log(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.",
263 MAX_CHORUS);
264 chorus->number_blocks = MAX_CHORUS;
265 }
266
267 if (chorus->speed_Hz < MIN_SPEED_HZ) {
268 fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
269 (double) MIN_SPEED_HZ);
270 chorus->speed_Hz = MIN_SPEED_HZ;
271 } else if (chorus->speed_Hz > MAX_SPEED_HZ) {
272 fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
273 (double) MAX_SPEED_HZ);
274 chorus->speed_Hz = MAX_SPEED_HZ;
275 }
276
277 if (chorus->depth_ms < 0.0) {
278 fluid_log(FLUID_WARN, "chorus: depth must be positive! Setting value to 0.");
279 chorus->depth_ms = 0.0;
280 }
281 /* Depth: Check for too high value through modulation_depth_samples. */
282
283 if (chorus->level < 0.0) {
284 fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
285 chorus->level = 0.0;
286 } else if (chorus->level > 10) {
287 fluid_log(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! "
288 "Setting it to 0.1.");
289 chorus->level = 0.1;
290 }
291
292 /* The modulating LFO goes through a full period every x samples: */
293 chorus->modulation_period_samples = chorus->sample_rate / chorus->speed_Hz;
294
295 /* The variation in delay time is x: */
296 modulation_depth_samples = (int)
297 (chorus->depth_ms / 1000.0 /* convert modulation depth in ms to s*/
298 * chorus->sample_rate);
299
300 if (modulation_depth_samples > MAX_SAMPLES) {
301 fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
302 modulation_depth_samples = MAX_SAMPLES;
303 }
304
305 /* initialize LFO table */
306 if (chorus->type == FLUID_CHORUS_MOD_SINE) {
307 fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
308 modulation_depth_samples);
309 } else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) {
310 fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
311 modulation_depth_samples);
312 } else {
313 fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
314 chorus->type = FLUID_CHORUS_MOD_SINE;
315 fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
316 modulation_depth_samples);
317 }
318
319 for (i = 0; i < chorus->number_blocks; i++) {
320 /* Set the phase of the chorus blocks equally spaced */
321 chorus->phase[i] = (int) ((double) chorus->modulation_period_samples
322 * (double) i / (double) chorus->number_blocks);
323 }
324
325 /* Start of the circular buffer */
326 chorus->counter = 0;
327 }
328
329
fluid_chorus_processmix(fluid_chorus_t * chorus,fluid_real_t * in,fluid_real_t * left_out,fluid_real_t * right_out)330 void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
331 fluid_real_t *left_out, fluid_real_t *right_out)
332 {
333 int sample_index;
334 int i;
335 fluid_real_t d_in, d_out;
336
337 for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) {
338
339 d_in = in[sample_index];
340 d_out = 0.0f;
341
342 # if 0
343 /* Debug: Listen to the chorus signal only */
344 left_out[sample_index]=0;
345 right_out[sample_index]=0;
346 #endif
347
348 /* Write the current sample into the circular buffer */
349 chorus->chorusbuf[chorus->counter] = d_in;
350
351 for (i = 0; i < chorus->number_blocks; i++) {
352 int ii;
353 /* Calculate the delay in subsamples for the delay line of chorus block nr. */
354
355 /* The value in the lookup table is so, that this expression
356 * will always be positive. It will always include a number of
357 * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
358 * remain positive at all times. */
359 int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
360 - chorus->lookup_tab[chorus->phase[i]]);
361
362 int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
363
364 /* modulo divide by INTERPOLATION_SUBSAMPLES */
365 pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
366
367 for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
368 /* Add the delayed signal to the chorus sum d_out Note: The
369 * delay in the delay line moves backwards for increasing
370 * delay!*/
371
372 /* The & in chorusbuf[...] is equivalent to a division modulo
373 MAX_SAMPLES, only faster. */
374 d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
375 * chorus->sinc_table[ii][pos_subsamples];
376
377 pos_samples--;
378 };
379 /* Cycle the phase of the modulating LFO */
380 chorus->phase[i]++;
381 chorus->phase[i] %= (chorus->modulation_period_samples);
382 } /* foreach chorus block */
383
384 d_out *= chorus->level;
385
386 /* Add the chorus sum d_out to output */
387 left_out[sample_index] += d_out;
388 right_out[sample_index] += d_out;
389
390 /* Move forward in circular buffer */
391 chorus->counter++;
392 chorus->counter %= MAX_SAMPLES;
393
394 } /* foreach sample */
395 }
396
397 /* Duplication of code ... (replaces sample data instead of mixing) */
fluid_chorus_processreplace(fluid_chorus_t * chorus,fluid_real_t * in,fluid_real_t * left_out,fluid_real_t * right_out)398 void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
399 fluid_real_t *left_out, fluid_real_t *right_out)
400 {
401 int sample_index;
402 int i;
403 fluid_real_t d_in, d_out;
404
405 for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) {
406
407 d_in = in[sample_index];
408 d_out = 0.0f;
409
410 # if 0
411 /* Debug: Listen to the chorus signal only */
412 left_out[sample_index]=0;
413 right_out[sample_index]=0;
414 #endif
415
416 /* Write the current sample into the circular buffer */
417 chorus->chorusbuf[chorus->counter] = d_in;
418
419 for (i = 0; i < chorus->number_blocks; i++) {
420 int ii;
421 /* Calculate the delay in subsamples for the delay line of chorus block nr. */
422
423 /* The value in the lookup table is so, that this expression
424 * will always be positive. It will always include a number of
425 * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
426 * remain positive at all times. */
427 int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
428 - chorus->lookup_tab[chorus->phase[i]]);
429
430 int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
431
432 /* modulo divide by INTERPOLATION_SUBSAMPLES */
433 pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
434
435 for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
436 /* Add the delayed signal to the chorus sum d_out Note: The
437 * delay in the delay line moves backwards for increasing
438 * delay!*/
439
440 /* The & in chorusbuf[...] is equivalent to a division modulo
441 MAX_SAMPLES, only faster. */
442 d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
443 * chorus->sinc_table[ii][pos_subsamples];
444
445 pos_samples--;
446 };
447 /* Cycle the phase of the modulating LFO */
448 chorus->phase[i]++;
449 chorus->phase[i] %= (chorus->modulation_period_samples);
450 } /* foreach chorus block */
451
452 d_out *= chorus->level;
453
454 /* Store the chorus sum d_out to output */
455 left_out[sample_index] = d_out;
456 right_out[sample_index] = d_out;
457
458 /* Move forward in circular buffer */
459 chorus->counter++;
460 chorus->counter %= MAX_SAMPLES;
461
462 } /* foreach sample */
463 }
464
465 /* Purpose:
466 *
467 * Calculates a modulation waveform (sine) Its value ( modulo
468 * MAXSAMPLES) varies between 0 and depth*INTERPOLATION_SUBSAMPLES.
469 * Its period length is len. The waveform data will be used modulo
470 * MAXSAMPLES only. Since MAXSAMPLES is substracted from the waveform
471 * a couple of times here, the resulting (current position in
472 * buffer)-(waveform sample) will always be positive.
473 */
474 static void
fluid_chorus_sine(int * buf,int len,int depth)475 fluid_chorus_sine(int *buf, int len, int depth)
476 {
477 int i;
478 double val;
479
480 for (i = 0; i < len; i++) {
481 val = sin((double) i / (double)len * 2.0 * M_PI);
482 buf[i] = (int) ((1.0 + val) * (double) depth / 2.0 * (double) INTERPOLATION_SUBSAMPLES);
483 buf[i] -= 3* MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
484 // printf("%i %i\n",i,buf[i]);
485 }
486 }
487
488 /* Purpose:
489 * Calculates a modulation waveform (triangle)
490 * See fluid_chorus_sine for comments.
491 */
492 static void
fluid_chorus_triangle(int * buf,int len,int depth)493 fluid_chorus_triangle(int *buf, int len, int depth)
494 {
495 int i=0;
496 int ii=len-1;
497 double val;
498 double val2;
499
500 while (i <= ii){
501 val = i * 2.0 / len * (double)depth * (double) INTERPOLATION_SUBSAMPLES;
502 val2= (int) (val + 0.5) - 3 * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
503 buf[i++] = (int) val2;
504 buf[ii--] = (int) val2;
505 }
506 }
507