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 */
106struct _fluid_chorus_t {
107  /* Store the values between fluid_chorus_set_xxx and fluid_chorus_update
108   * Logic behind this:
109   * - both 'parameter' and 'new_parameter' hold the same value.
110   * - To change the chorus settings, 'new_parameter' is modified and
111   *   fluid_chorus_update is called.
112   * - If the new value is valid, it is copied to 'parameter'.
113   * - If it is invalid, 'new_parameter' is restored to 'parameter'.
114   */
115  int type;                  /* current value */
116  int new_type;              /* next value, if parameter check is OK */
117  fluid_real_t depth_ms;      /* current value */
118  fluid_real_t new_depth_ms;  /* next value, if parameter check is OK */
119  fluid_real_t level;         /* current value */
120  fluid_real_t new_level;     /* next value, if parameter check is OK */
121  fluid_real_t speed_Hz;      /* current value */
122  fluid_real_t new_speed_Hz;  /* next value, if parameter check is OK */
123  int number_blocks;         /* current value */
124  int new_number_blocks;     /* next value, if parameter check is OK */
125
126  fluid_real_t *chorusbuf;
127  int counter;
128  long phase[MAX_CHORUS];
129  long modulation_period_samples;
130  int *lookup_tab;
131  fluid_real_t sample_rate;
132
133  /* sinc lookup table */
134  fluid_real_t sinc_table[INTERPOLATION_SAMPLES][INTERPOLATION_SUBSAMPLES];
135};
136
137void fluid_chorus_triangle(int *buf, int len, int depth);
138void fluid_chorus_sine(int *buf, int len, int depth);
139
140fluid_chorus_t*
141new_fluid_chorus(fluid_real_t sample_rate)
142{
143  int i; int ii;
144  fluid_chorus_t* chorus;
145
146  chorus = FLUID_NEW(fluid_chorus_t);
147  if (chorus == NULL) {
148    fluid_log(FLUID_PANIC, "chorus: Out of memory");
149    return NULL;
150  }
151
152  FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t));
153
154  chorus->sample_rate = sample_rate;
155
156  /* Lookup table for the SI function (impulse response of an ideal low pass) */
157
158  /* i: Offset in terms of whole samples */
159  for (i = 0; i < INTERPOLATION_SAMPLES; i++){
160
161    /* ii: Offset in terms of fractional samples ('subsamples') */
162    for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){
163      /* Move the origin into the center of the table */
164      double i_shifted = ((double) i- ((double) INTERPOLATION_SAMPLES) / 2.
165			  + (double) ii / (double) INTERPOLATION_SUBSAMPLES);
166      if (fabs(i_shifted) < 0.000001) {
167	/* sinc(0) cannot be calculated straightforward (limit needed
168	   for 0/0) */
169	chorus->sinc_table[i][ii] = (fluid_real_t)1.;
170
171      } else {
172	chorus->sinc_table[i][ii] = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted);
173	/* Hamming window */
174	chorus->sinc_table[i][ii] *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)INTERPOLATION_SAMPLES));
175      };
176    };
177  };
178
179  /* allocate lookup tables */
180  chorus->lookup_tab = FLUID_ARRAY(int, (int) (chorus->sample_rate / MIN_SPEED_HZ));
181  if (chorus->lookup_tab == NULL) {
182    fluid_log(FLUID_PANIC, "chorus: Out of memory");
183    goto error_recovery;
184  }
185
186  /* allocate sample buffer */
187
188  chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
189  if (chorus->chorusbuf == NULL) {
190    fluid_log(FLUID_PANIC, "chorus: Out of memory");
191    goto error_recovery;
192  }
193
194  if (fluid_chorus_init(chorus) != FLUID_OK){
195    goto error_recovery;
196  };
197
198  return chorus;
199
200 error_recovery:
201  delete_fluid_chorus(chorus);
202  return NULL;
203}
204
205
206int
207fluid_chorus_init(fluid_chorus_t* chorus)
208{
209  int i;
210
211  for (i = 0; i < MAX_SAMPLES; i++) {
212    chorus->chorusbuf[i] = 0.0;
213  }
214
215  /* initialize the chorus with the default settings */
216  fluid_chorus_set_nr(chorus, FLUID_CHORUS_DEFAULT_N);
217  fluid_chorus_set_level(chorus, FLUID_CHORUS_DEFAULT_LEVEL);
218  fluid_chorus_set_speed_Hz(chorus, FLUID_CHORUS_DEFAULT_SPEED);
219  fluid_chorus_set_depth_ms(chorus, FLUID_CHORUS_DEFAULT_DEPTH);
220  fluid_chorus_set_type(chorus, FLUID_CHORUS_MOD_SINE);
221
222  return fluid_chorus_update(chorus);
223}
224
225/* Purpose:
226 * Sets the number of stages.
227 * Requires call to fluid_chorus_update afterwards.
228 * Range checking is performed there.*/
229void fluid_chorus_set_nr(fluid_chorus_t* chorus, int nr)
230{
231  chorus->new_number_blocks = nr;
232}
233
234/* Purpose:
235 * API function, read the current state of the chorus
236 */
237int fluid_chorus_get_nr(fluid_chorus_t* chorus)
238{
239    return chorus->number_blocks;
240};
241
242/* Purpose:
243 * Sets the mixing level of the signal from each delay line (linear).
244 * Requires calling fluid_chorus_update afterwards.*/
245void fluid_chorus_set_level(fluid_chorus_t* chorus, fluid_real_t level)
246{
247  chorus->new_level = level;
248}
249
250/* Purpose:
251 * API function, read the current state of the chorus
252 */
253fluid_real_t fluid_chorus_get_level(fluid_chorus_t* chorus)
254{
255    return chorus->level;
256};
257
258/* Purpose:
259 * Sets the modulation frequency.
260 * Requires call to fluid_chorus_update afterwards.
261 * Range checking is performed there.*/
262void fluid_chorus_set_speed_Hz(fluid_chorus_t* chorus, fluid_real_t speed_Hz)
263{
264  chorus->new_speed_Hz = speed_Hz;
265}
266
267/* Purpose:
268 * API function, read the current state of the chorus
269 */
270fluid_real_t fluid_chorus_get_speed_Hz(fluid_chorus_t* chorus)
271{
272    return chorus->speed_Hz;
273};
274
275/* Purpose:
276 * Sets the modulation depth in ms.
277 * Requires call to fluid_chorus_update afterwards.
278 * Range checking is performed there.*/
279void fluid_chorus_set_depth_ms(fluid_chorus_t* chorus, fluid_real_t depth_ms)
280{
281  chorus->new_depth_ms=depth_ms;
282}
283
284/* Purpose:
285 * API function, read the current state of the chorus
286 */
287fluid_real_t fluid_chorus_get_depth_ms(fluid_chorus_t* chorus)
288{
289    return chorus->depth_ms;
290};
291
292/* Purpose:
293 * Sets the type of the modulation waveform.
294 * Requires call to fluid_chorus_update afterwards.
295 * Check for meaningful values is performed there.*/
296void fluid_chorus_set_type(fluid_chorus_t* chorus, int type)
297{
298  chorus->new_type=type;
299}
300
301/* Purpose:
302 * API function, read the current state of the chorus
303 */
304int fluid_chorus_get_type(fluid_chorus_t* chorus)
305{
306    return chorus->type;
307};
308
309void
310delete_fluid_chorus(fluid_chorus_t* chorus)
311{
312  if (chorus == NULL) {
313    return;
314  }
315
316  if (chorus->chorusbuf != NULL) {
317    FLUID_FREE(chorus->chorusbuf);
318  }
319
320  if (chorus->lookup_tab != NULL) {
321    FLUID_FREE(chorus->lookup_tab);
322  }
323
324  FLUID_FREE(chorus);
325}
326
327
328/* Purpose:
329 * Calculates the internal chorus parameters using the settings from
330 * fluid_chorus_set_xxx. */
331int
332fluid_chorus_update(fluid_chorus_t* chorus)
333{
334  int i;
335  int modulation_depth_samples;
336
337  if (chorus->new_number_blocks < 0) {
338    fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
339    chorus->new_number_blocks = 0;
340  } else if (chorus->new_number_blocks > MAX_CHORUS) {
341    fluid_log(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.",
342	     MAX_CHORUS);
343    chorus->new_number_blocks = MAX_CHORUS;
344  };
345
346  if (chorus->new_speed_Hz < MIN_SPEED_HZ) {
347    fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
348	     (double) MIN_SPEED_HZ);
349    chorus->new_speed_Hz = MIN_SPEED_HZ;
350  } else if (chorus->new_speed_Hz > MAX_SPEED_HZ) {
351    fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
352	     (double) MAX_SPEED_HZ);
353    chorus->new_speed_Hz = MAX_SPEED_HZ;
354  }
355  if (chorus->new_depth_ms < 0.0) {
356    fluid_log(FLUID_WARN, "chorus: depth must be positive! Setting value to 0.");
357    chorus->new_depth_ms = 0.0;
358  }
359  /* Depth: Check for too high value through modulation_depth_samples. */
360
361  if (chorus->new_level < 0.0) {
362    fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
363    chorus->new_level = 0.0;
364  } else if (chorus->new_level > 10) {
365    fluid_log(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! "
366	     "Setting it to 0.1.");
367    chorus->new_level = 0.1;
368  }
369
370  /* The modulating LFO goes through a full period every x samples: */
371  chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz;
372
373  /* The variation in delay time is x: */
374  modulation_depth_samples = (int)
375    (chorus->new_depth_ms / 1000.0  /* convert modulation depth in ms to s*/
376     * chorus->sample_rate);
377
378  if (modulation_depth_samples > MAX_SAMPLES) {
379    fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
380    modulation_depth_samples = MAX_SAMPLES;
381  }
382
383  /* initialize LFO table */
384  if (chorus->type == FLUID_CHORUS_MOD_SINE) {
385    fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
386		     modulation_depth_samples);
387  } else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) {
388    fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
389			 modulation_depth_samples);
390  } else {
391    fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
392    chorus->type = FLUID_CHORUS_MOD_SINE;
393    fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
394		     modulation_depth_samples);
395  };
396
397  for (i = 0; i < chorus->number_blocks; i++) {
398    /* Set the phase of the chorus blocks equally spaced */
399    chorus->phase[i] = (int) ((double) chorus->modulation_period_samples
400			      * (double) i / (double) chorus->number_blocks);
401  }
402
403  /* Start of the circular buffer */
404  chorus->counter = 0;
405
406  chorus->type = chorus->new_type;
407  chorus->depth_ms = chorus->new_depth_ms;
408  chorus->level = chorus->new_level;
409  chorus->speed_Hz = chorus->new_speed_Hz;
410  chorus->number_blocks = chorus->new_number_blocks;
411  return FLUID_OK;
412
413/*  failure: */
414  /* Note: This lives on the assumption, that the last chorus values were correct.
415   * If not, this will loop forever and a day. */
416/*   fluid_log(FLUID_WARN, "chorus: Restoring last good settings"); */
417/*   chorus->new_type = chorus->type; */
418/*   chorus->new_depth_ms = chorus->depth_ms; */
419/*   chorus->new_level = chorus->level; */
420/*   chorus->new_speed_Hz = chorus->speed_Hz; */
421/*   chorus->new_number_blocks = chorus->number_blocks; */
422/*   return FLUID_FAILED; */
423}
424
425
426void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in,
427			    fluid_real_t *left_out, fluid_real_t *right_out)
428{
429  int sample_index;
430  int i;
431  fluid_real_t d_in, d_out;
432
433  for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) {
434
435    d_in = in[sample_index];
436    d_out = 0.0f;
437
438# if 0
439    /* Debug: Listen to the chorus signal only */
440    left_out[sample_index]=0;
441    right_out[sample_index]=0;
442#endif
443
444    /* Write the current sample into the circular buffer */
445    chorus->chorusbuf[chorus->counter] = d_in;
446
447    for (i = 0; i < chorus->number_blocks; i++) {
448      int ii;
449      /* Calculate the delay in subsamples for the delay line of chorus block nr. */
450
451      /* The value in the lookup table is so, that this expression
452       * will always be positive.  It will always include a number of
453       * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
454       * remain positive at all times. */
455      int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
456			    - chorus->lookup_tab[chorus->phase[i]]);
457
458      int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES;
459
460      /* modulo divide by INTERPOLATION_SUBSAMPLES */
461      pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
462
463      for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
464	/* Add the delayed signal to the chorus sum d_out Note: The
465	 * delay in the delay line moves backwards for increasing
466	 * delay!*/
467
468	/* The & in chorusbuf[...] is equivalent to a division modulo
469	   MAX_SAMPLES, only faster. */
470	d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
471	  * chorus->sinc_table[ii][pos_subsamples];
472
473	pos_samples--;
474      };
475      /* Cycle the phase of the modulating LFO */
476      chorus->phase[i]++;
477      chorus->phase[i] %= (chorus->modulation_period_samples);
478    } /* foreach chorus block */
479
480    d_out *= chorus->level;
481
482    /* Add the chorus sum d_out to output */
483    left_out[sample_index] += d_out;
484    right_out[sample_index] += d_out;
485
486    /* Move forward in circular buffer */
487    chorus->counter++;
488    chorus->counter %= MAX_SAMPLES;
489
490  } /* foreach sample */
491}
492
493/* Duplication of code ... (replaces sample data instead of mixing) */
494void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in,
495				fluid_real_t *left_out, fluid_real_t *right_out)
496{
497  int sample_index;
498  int i;
499  fluid_real_t d_in, d_out;
500
501  for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) {
502
503    d_in = in[sample_index];
504    d_out = 0.0f;
505
506# if 0
507    /* Debug: Listen to the chorus signal only */
508    left_out[sample_index]=0;
509    right_out[sample_index]=0;
510#endif
511
512    /* Write the current sample into the circular buffer */
513    chorus->chorusbuf[chorus->counter] = d_in;
514
515    for (i = 0; i < chorus->number_blocks; i++) {
516      int ii;
517      /* Calculate the delay in subsamples for the delay line of chorus block nr. */
518
519      /* The value in the lookup table is so, that this expression
520       * will always be positive.  It will always include a number of
521       * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
522       * remain positive at all times. */
523      int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
524			    - chorus->lookup_tab[chorus->phase[i]]);
525
526      int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
527
528      /* modulo divide by INTERPOLATION_SUBSAMPLES */
529      pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
530
531      for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){
532	/* Add the delayed signal to the chorus sum d_out Note: The
533	 * delay in the delay line moves backwards for increasing
534	 * delay!*/
535
536	/* The & in chorusbuf[...] is equivalent to a division modulo
537	   MAX_SAMPLES, only faster. */
538	d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
539	  * chorus->sinc_table[ii][pos_subsamples];
540
541	pos_samples--;
542      };
543      /* Cycle the phase of the modulating LFO */
544      chorus->phase[i]++;
545      chorus->phase[i] %= (chorus->modulation_period_samples);
546    } /* foreach chorus block */
547
548    d_out *= chorus->level;
549
550    /* Store the chorus sum d_out to output */
551    left_out[sample_index] = d_out;
552    right_out[sample_index] = d_out;
553
554    /* Move forward in circular buffer */
555    chorus->counter++;
556    chorus->counter %= MAX_SAMPLES;
557
558  } /* foreach sample */
559}
560
561/* Purpose:
562 *
563 * Calculates a modulation waveform (sine) Its value ( modulo
564 * MAXSAMPLES) varies between 0 and depth*INTERPOLATION_SUBSAMPLES.
565 * Its period length is len.  The waveform data will be used modulo
566 * MAXSAMPLES only.  Since MAXSAMPLES is substracted from the waveform
567 * a couple of times here, the resulting (current position in
568 * buffer)-(waveform sample) will always be positive.
569 */
570void fluid_chorus_sine(int *buf, int len, int depth)
571{
572  int i;
573  double val;
574
575  for (i = 0; i < len; i++) {
576    val = sin((double) i / (double)len * 2.0 * M_PI);
577    buf[i] = (int) ((1.0 + val) * (double) depth / 2.0 * (double) INTERPOLATION_SUBSAMPLES);
578    buf[i] -= 3* MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
579    //    printf("%i %i\n",i,buf[i]);
580  }
581}
582
583/* Purpose:
584 * Calculates a modulation waveform (triangle)
585 * See fluid_chorus_sine for comments.
586 */
587void fluid_chorus_triangle(int *buf, int len, int depth)
588{
589  int i=0;
590  int ii=len-1;
591  double val;
592  double val2;
593
594  while (i <= ii){
595    val = i * 2.0 / len * (double)depth * (double) INTERPOLATION_SUBSAMPLES;
596    val2= (int) (val + 0.5) - 3 * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
597    buf[i++] = (int) val2;
598    buf[ii--] = (int) val2;
599  }
600}
601
602void
603fluid_chorus_reset(fluid_chorus_t* chorus)
604{
605  fluid_chorus_init(chorus);
606}
607