1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe, Markus Nentwig and others.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 based on a chrous implementation made by Juergen Mueller And Sundry Contributors in 1998
26 - Adapted for fluidsynth, Peter Hanappe, March 2002
28 - Variable delay line implementation using bandlimited
29 interpolation, code reorganization: Markus Nentwig May 2002
37 * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
40 * ibuff -----+--------------------------------------------->| |
43 * +---->| delay 1 |----------------------------->| |
47 * : +-----------------+ +--------------+ | + |
48 * : | Delay control 1 |<--| mod. speed 1 | | |
49 * : +-----------------+ +--------------+ | |
52 * +---->| delay n |----------------------------->| |
56 * +-----------------+ +--------------+ | * gain-out
57 * | Delay control n |<--| mod. speed n | |
58 * +-----------------+ +--------------+ +----->obuff
61 * The delay i is controlled by a sine or triangle modulation i ( 1 <= i <= n).
63 * The delay of each block is modulated between 0..depth ms
68 /* Variable delay line implementation
69 * ==================================
71 * The modulated delay needs the value of the delayed signal between
72 * samples. A lowpass filter is used to obtain intermediate values
73 * between samples (bandlimited interpolation). The sample pulse
74 * train is convoluted with the impulse response of the low pass
75 * filter (sinc function). To make it work with a small number of
76 * samples, the sinc function is windowed (Hamming window).
80 #include "fluid_chorus.h"
81 #include "fluid_sys.h"
86 #define MIN_SPEED_HZ 0.29
87 #define MAX_SPEED_HZ 5
89 /* Length of one delay line in samples:
90 * Set through MAX_SAMPLES_LN2.
93 * => MAX_SAMPLES=pow(2,12-1)=2048
94 * => MAX_SAMPLES_ANDMASK=2047
96 #define MAX_SAMPLES_LN2 12
98 #define MAX_SAMPLES (1 << (MAX_SAMPLES_LN2-1))
99 #define MAX_SAMPLES_ANDMASK (MAX_SAMPLES-1)
102 /* Interpolate how many steps between samples? Must be power of two
103 For example: 8 => use a resolution of 256 steps between any two
106 #define INTERPOLATION_SUBSAMPLES_LN2 8
107 #define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1))
108 #define INTERPOLATION_SUBSAMPLES_ANDMASK (INTERPOLATION_SUBSAMPLES-1)
110 /* Use how many samples for interpolation? Must be odd. '7' sounds
111 relatively clean, when listening to the modulated delay signal
112 alone. For a demo on aliasing try '1' With '3', the aliasing is
113 still quite pronounced for some input frequencies
115 #define INTERPOLATION_SAMPLES 5
117 /* Private data for SKEL file */
118 struct _fluid_chorus_t
121 fluid_real_t depth_ms;
123 fluid_real_t speed_Hz;
126 fluid_real_t *chorusbuf;
128 long phase[MAX_CHORUS];
129 long modulation_period_samples;
131 fluid_real_t sample_rate;
133 /* sinc lookup table */
134 fluid_real_t sinc_table[INTERPOLATION_SAMPLES][INTERPOLATION_SUBSAMPLES];
137 static void fluid_chorus_triangle(int *buf, int len, int depth);
138 static void fluid_chorus_sine(int *buf, int len, int depth);
142 new_fluid_chorus(fluid_real_t sample_rate)
146 fluid_chorus_t *chorus;
148 chorus = FLUID_NEW(fluid_chorus_t);
152 FLUID_LOG(FLUID_PANIC, "chorus: Out of memory");
156 FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t));
158 chorus->sample_rate = sample_rate;
160 /* Lookup table for the SI function (impulse response of an ideal low pass) */
162 /* i: Offset in terms of whole samples */
163 for(i = 0; i < INTERPOLATION_SAMPLES; i++)
166 /* ii: Offset in terms of fractional samples ('subsamples') */
167 for(ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++)
169 /* Move the origin into the center of the table */
170 double i_shifted = ((double) i - ((double) INTERPOLATION_SAMPLES) / 2.
171 + (double) ii / (double) INTERPOLATION_SUBSAMPLES);
173 if(fabs(i_shifted) < 0.000001)
175 /* sinc(0) cannot be calculated straightforward (limit needed
177 chorus->sinc_table[i][ii] = (fluid_real_t)1.;
182 chorus->sinc_table[i][ii] = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted);
184 chorus->sinc_table[i][ii] *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)INTERPOLATION_SAMPLES));
189 /* allocate lookup tables */
190 chorus->lookup_tab = FLUID_ARRAY(int, (int)(chorus->sample_rate / MIN_SPEED_HZ));
192 if(chorus->lookup_tab == NULL)
194 FLUID_LOG(FLUID_PANIC, "chorus: Out of memory");
198 /* allocate sample buffer */
200 chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES);
202 if(chorus->chorusbuf == NULL)
204 FLUID_LOG(FLUID_PANIC, "chorus: Out of memory");
208 if(fluid_chorus_init(chorus) != FLUID_OK)
216 delete_fluid_chorus(chorus);
222 delete_fluid_chorus(fluid_chorus_t *chorus)
224 fluid_return_if_fail(chorus != NULL);
226 FLUID_FREE(chorus->chorusbuf);
227 FLUID_FREE(chorus->lookup_tab);
232 fluid_chorus_init(fluid_chorus_t *chorus)
236 for(i = 0; i < MAX_SAMPLES; i++)
238 chorus->chorusbuf[i] = 0.0;
245 fluid_chorus_reset(fluid_chorus_t *chorus)
247 fluid_chorus_init(chorus);
251 * Set one or more chorus parameters.
252 * @param chorus Chorus instance
253 * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
254 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
256 * @param level Chorus level (0.0-10.0)
257 * @param speed Chorus speed in Hz (0.29-5.0)
258 * @param depth_ms Chorus depth (max value depends on synth sample rate,
259 * 0.0-21.0 is safe for sample rate values up to 96KHz)
260 * @param type Chorus waveform type (#fluid_chorus_mod)
263 fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level,
264 fluid_real_t speed, fluid_real_t depth_ms, int type)
266 int modulation_depth_samples;
269 if(set & FLUID_CHORUS_SET_NR)
271 chorus->number_blocks = nr;
274 if(set & FLUID_CHORUS_SET_LEVEL)
276 chorus->level = level;
279 if(set & FLUID_CHORUS_SET_SPEED)
281 chorus->speed_Hz = speed;
284 if(set & FLUID_CHORUS_SET_DEPTH)
286 chorus->depth_ms = depth_ms;
289 if(set & FLUID_CHORUS_SET_TYPE)
294 if(chorus->number_blocks < 0)
296 FLUID_LOG(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
297 chorus->number_blocks = 0;
299 else if(chorus->number_blocks > MAX_CHORUS)
301 FLUID_LOG(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.",
303 chorus->number_blocks = MAX_CHORUS;
306 if(chorus->speed_Hz < MIN_SPEED_HZ)
308 FLUID_LOG(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
309 (double) MIN_SPEED_HZ);
310 chorus->speed_Hz = MIN_SPEED_HZ;
312 else if(chorus->speed_Hz > MAX_SPEED_HZ)
314 FLUID_LOG(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
315 (double) MAX_SPEED_HZ);
316 chorus->speed_Hz = MAX_SPEED_HZ;
319 if(chorus->depth_ms < 0.0)
321 FLUID_LOG(FLUID_WARN, "chorus: depth must be positive! Setting value to 0.");
322 chorus->depth_ms = 0.0;
325 /* Depth: Check for too high value through modulation_depth_samples. */
327 if(chorus->level < 0.0)
329 FLUID_LOG(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
332 else if(chorus->level > 10)
334 FLUID_LOG(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! "
335 "Setting it to 0.1.");
339 /* The modulating LFO goes through a full period every x samples: */
340 chorus->modulation_period_samples = chorus->sample_rate / chorus->speed_Hz;
342 /* The variation in delay time is x: */
343 modulation_depth_samples = (int)
344 (chorus->depth_ms / 1000.0 /* convert modulation depth in ms to s*/
345 * chorus->sample_rate);
347 if(modulation_depth_samples > MAX_SAMPLES)
349 FLUID_LOG(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES);
350 modulation_depth_samples = MAX_SAMPLES;
351 // set depth to maximum to avoid spamming console with above warning
352 chorus->depth_ms = (modulation_depth_samples * 1000) / chorus->sample_rate;
355 /* initialize LFO table */
359 FLUID_LOG(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
360 chorus->type = FLUID_CHORUS_MOD_SINE;
363 case FLUID_CHORUS_MOD_SINE:
364 fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples,
365 modulation_depth_samples);
368 case FLUID_CHORUS_MOD_TRIANGLE:
369 fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples,
370 modulation_depth_samples);
374 for(i = 0; i < chorus->number_blocks; i++)
376 /* Set the phase of the chorus blocks equally spaced */
377 chorus->phase[i] = (int)((double) chorus->modulation_period_samples
378 * (double) i / (double) chorus->number_blocks);
381 /* Start of the circular buffer */
386 void fluid_chorus_processmix(fluid_chorus_t *chorus, const fluid_real_t *in,
387 fluid_real_t *left_out, fluid_real_t *right_out)
391 fluid_real_t d_in, d_out;
393 for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++)
396 d_in = in[sample_index];
400 /* Debug: Listen to the chorus signal only */
401 left_out[sample_index] = 0;
402 right_out[sample_index] = 0;
405 /* Write the current sample into the circular buffer */
406 chorus->chorusbuf[chorus->counter] = d_in;
408 for(i = 0; i < chorus->number_blocks; i++)
411 /* Calculate the delay in subsamples for the delay line of chorus block nr. */
413 /* The value in the lookup table is so, that this expression
414 * will always be positive. It will always include a number of
415 * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
416 * remain positive at all times. */
417 int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
418 - chorus->lookup_tab[chorus->phase[i]]);
420 int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
422 /* modulo divide by INTERPOLATION_SUBSAMPLES */
423 pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
425 for(ii = 0; ii < INTERPOLATION_SAMPLES; ii++)
427 /* Add the delayed signal to the chorus sum d_out Note: The
428 * delay in the delay line moves backwards for increasing
431 /* The & in chorusbuf[...] is equivalent to a division modulo
432 MAX_SAMPLES, only faster. */
433 d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
434 * chorus->sinc_table[ii][pos_subsamples];
439 /* Cycle the phase of the modulating LFO */
442 chorus->phase[i] %= (chorus->modulation_period_samples);
443 } /* foreach chorus block */
445 d_out *= chorus->level;
447 /* Add the chorus sum d_out to output */
448 left_out[sample_index] += d_out;
449 right_out[sample_index] += d_out;
451 /* Move forward in circular buffer */
453 chorus->counter %= MAX_SAMPLES;
455 } /* foreach sample */
458 /* Duplication of code ... (replaces sample data instead of mixing) */
459 void fluid_chorus_processreplace(fluid_chorus_t *chorus, const fluid_real_t *in,
460 fluid_real_t *left_out, fluid_real_t *right_out)
464 fluid_real_t d_in, d_out;
466 for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++)
469 d_in = in[sample_index];
473 /* Debug: Listen to the chorus signal only */
474 left_out[sample_index] = 0;
475 right_out[sample_index] = 0;
478 /* Write the current sample into the circular buffer */
479 chorus->chorusbuf[chorus->counter] = d_in;
481 for(i = 0; i < chorus->number_blocks; i++)
484 /* Calculate the delay in subsamples for the delay line of chorus block nr. */
486 /* The value in the lookup table is so, that this expression
487 * will always be positive. It will always include a number of
488 * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to
489 * remain positive at all times. */
490 int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter
491 - chorus->lookup_tab[chorus->phase[i]]);
493 int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES;
495 /* modulo divide by INTERPOLATION_SUBSAMPLES */
496 pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK;
498 for(ii = 0; ii < INTERPOLATION_SAMPLES; ii++)
500 /* Add the delayed signal to the chorus sum d_out Note: The
501 * delay in the delay line moves backwards for increasing
504 /* The & in chorusbuf[...] is equivalent to a division modulo
505 MAX_SAMPLES, only faster. */
506 d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK]
507 * chorus->sinc_table[ii][pos_subsamples];
512 /* Cycle the phase of the modulating LFO */
515 chorus->phase[i] %= (chorus->modulation_period_samples);
516 } /* foreach chorus block */
518 d_out *= chorus->level;
520 /* Store the chorus sum d_out to output */
521 left_out[sample_index] = d_out;
522 right_out[sample_index] = d_out;
524 /* Move forward in circular buffer */
526 chorus->counter %= MAX_SAMPLES;
528 } /* foreach sample */
533 * Calculates a modulation waveform (sine) Its value ( modulo
534 * MAXSAMPLES) varies between 0 and depth*INTERPOLATION_SUBSAMPLES.
535 * Its period length is len. The waveform data will be used modulo
536 * MAXSAMPLES only. Since MAXSAMPLES is substracted from the waveform
537 * a couple of times here, the resulting (current position in
538 * buffer)-(waveform sample) will always be positive.
541 fluid_chorus_sine(int *buf, int len, int depth)
544 double angle, incr, mult;
546 /* Pre-calculate increment between angles. */
547 incr = (2. * M_PI) / (double)len;
549 /* Pre-calculate 'depth' multiplier. */
550 mult = (double) depth / 2.0 * (double) INTERPOLATION_SUBSAMPLES;
552 /* Initialize to zero degrees. */
555 /* Build sine modulation waveform */
556 for(i = 0; i < len; i++)
558 buf[i] = (int)((1. + sin(angle)) * mult) - 3 * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
565 * Calculates a modulation waveform (triangle)
566 * See fluid_chorus_sine for comments.
569 fluid_chorus_triangle(int *buf, int len, int depth)
572 int *ir = buf + len - 1;
576 /* Pre-calculate increment for the ramp. */
577 incr = 2.0 / len * (double)depth * (double) INTERPOLATION_SUBSAMPLES;
579 /* Initialize first value */
580 val = 0. - 3. * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES;
582 /* Build triangular modulation waveform */
585 /* Assume 'val' to be always negative for rounding mode */
586 ival = (int)(val - 0.5);