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