Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/rvoice/fluid_chorus.c
4396 views
1
/* FluidSynth - A Software Synthesizer
2
*
3
* Copyright (C) 2003 Peter Hanappe, Markus Nentwig and others.
4
*
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.
9
*
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.
14
*
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
18
* 02110-1301, USA
19
*/
20
21
/*
22
based on a chorus implementation made by Juergen Mueller And Sundry Contributors in 1998
23
24
CHANGES
25
26
- Adapted for fluidsynth, Peter Hanappe, March 2002
27
28
- Variable delay line implementation using bandlimited
29
interpolation, code reorganization: Markus Nentwig May 2002
30
31
- Complete rewrite using lfo computed on the fly, first order all-pass
32
interpolator and adding stereo unit: Jean-Jacques Ceresa, Jul 2019
33
*/
34
35
36
/*
37
* Chorus effect.
38
*
39
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
40
*
41
* ________
42
* direct signal (not implemented) >-->| |
43
* _________ | |
44
* mono | | | |
45
* input ---+---->| delay 1 |-------------------------->| Stereo |---> right
46
* | |_________| | | output
47
* | /|\ | Unit |
48
* : | | |
49
* : +-----------------+ |(width) |
50
* : | Delay control 1 |<-+ | |
51
* : +-----------------+ | | |---> left
52
* | _________ | | | output
53
* | | | | | |
54
* +---->| delay n |-------------------------->| |
55
* |_________| | | |
56
* /|\ | |________|
57
* | | +--------------+ /|\
58
* +-----------------+ | |mod depth (ms)| |
59
* | Delay control n |<-*--|lfo speed (Hz)| gain-out
60
* +-----------------+ +--------------+
61
*
62
*
63
* The delay i is controlled by a sine or triangle modulation i ( 1 <= i <= n).
64
*
65
* The chorus unit process a monophonic input signal and produces stereo output
66
* controlled by WIDTH macro.
67
* Actually WIDTH is fixed to maximum value. But in the future, we could add a
68
* setting (e.g "synth.chorus.width") allowing the user to get a gradually stereo
69
* effect from minimum (monophonic) to maximum stereo effect.
70
*
71
* Delays lines are implemented using only one line for all chorus blocks.
72
* Each chorus block has it own lfo (sinus/triangle). Each lfo are out of phase
73
* to produce uncorrelated signal at the output of the delay line (this simulates
74
* the presence of individual line for each block). Each lfo modulates the length
75
* of the line using a depth modulation value and lfo frequency value common to
76
* all lfos.
77
*
78
* LFO modulators are computed on the fly, instead of using lfo lookup table.
79
* The advantages are:
80
* - Avoiding a lost of 608272 memory bytes when lfo speed is low (0.3Hz).
81
* - Allows to diminish the lfo speed lower limit to 0.1Hz instead of 0.3Hz.
82
* A speed of 0.1 is interesting for chorus. Using a lookuptable for 0.1Hz
83
* would require too much memory (1824816 bytes).
84
* - Interpolation make use of first order all-pass interpolator instead of
85
* bandlimited interpolation.
86
* - Although lfo modulator is computed on the fly, cpu load is lower than
87
* using lfo lookup table with bandlimited interpolator.
88
*/
89
90
#include "fluid_chorus.h"
91
#include "fluid_sys.h"
92
93
94
/*-------------------------------------------------------------------------------------
95
Private
96
--------------------------------------------------------------------------------------*/
97
// #define DEBUG_PRINT // allows message to be printed on the console.
98
99
#define MAX_CHORUS 99 /* number maximum of block */
100
#define MAX_LEVEL 10 /* max output level */
101
#define MIN_SPEED_HZ 0.1 /* min lfo frequency (Hz) */
102
#define MAX_SPEED_HZ 5 /* max lfo frequency (Hz) */
103
104
/* WIDTH [0..10] value define a stereo separation between left and right.
105
When 0, the output is monophonic. When > 0 , the output is stereophonic.
106
Actually WIDTH is fixed to maximum value. But in the future we could add a setting to
107
allow a gradually stereo effect from minimum (monophonic) to maximum stereo effect.
108
*/
109
#define WIDTH 10
110
111
/* SCALE_WET_WIDTH is a compensation weight factor to get an output
112
amplitude (wet) rather independent of the width setting.
113
0: the output amplitude is fully dependent on the width setting.
114
>0: the output amplitude is less dependent on the width setting.
115
With a SCALE_WET_WIDTH of 0.2 the output amplitude is rather
116
independent of width setting (see fluid_chorus_set()).
117
*/
118
#define SCALE_WET_WIDTH 0.2f
119
#define SCALE_WET 1.0f
120
121
#define MAX_SAMPLES 2048 /* delay length in sample (46.4 ms at sample rate: 44100Hz).*/
122
#define LOW_MOD_DEPTH 176 /* low mod_depth/2 in samples */
123
#define HIGH_MOD_DEPTH MAX_SAMPLES/2 /* high mod_depth in sample */
124
#define RANGE_MOD_DEPTH (HIGH_MOD_DEPTH - LOW_MOD_DEPTH)
125
126
/* Important min max values for MOD_RATE */
127
/* mod rate define the rate at which the modulator is updated. Examples
128
50: the modulator is updated every 50 samples (less cpu cycles expensive).
129
1: the modulator is updated every sample (more cpu cycles expensive).
130
*/
131
/* MOD_RATE acceptable for max lfo speed (5Hz) and max modulation depth (46.6 ms) */
132
#define LOW_MOD_RATE 5 /* MOD_RATE acceptable for low modulation depth (8 ms) */
133
#define HIGH_MOD_RATE 4 /* MOD_RATE acceptable for max modulation depth (46.6 ms) */
134
/* and max lfo speed (5 Hz) */
135
#define RANGE_MOD_RATE (HIGH_MOD_RATE - LOW_MOD_RATE)
136
137
/* some chorus cpu_load measurement dependent of modulation rate: mod_rate
138
(number of chorus blocks: 2)
139
140
No stero unit:
141
mod_rate | chorus cpu load(%) | one voice cpu load (%)
142
----------------------------------------------------
143
50 | 0.204 |
144
5 | 0.256 | 0.169
145
1 | 0.417 |
146
147
With stero unit:
148
mod_rate | chorus cpu load(%) | one voice cpu load (%)
149
----------------------------------------------------
150
50 | 0.220 |
151
5 | 0.274 | 0.169
152
1 | 0.465 |
153
154
*/
155
156
/*
157
Number of samples to add to the desired length of the delay line. This
158
allows to take account of rounding error interpolation when using large
159
modulation depth.
160
1 is sufficient for max modulation depth (46.6 ms) and max lfo speed (5 Hz).
161
*/
162
//#define INTERP_SAMPLES_NBR 0
163
#define INTERP_SAMPLES_NBR 1
164
165
166
/*-----------------------------------------------------------------------------
167
Sinusoidal modulator
168
-----------------------------------------------------------------------------*/
169
/* modulator */
170
typedef struct
171
{
172
// for sufficient precision members MUST be double! See https://github.com/FluidSynth/fluidsynth/issues/1331
173
double a1; /* Coefficient: a1 = 2 * cos(w) */
174
double buffer1; /* buffer1 */
175
double buffer2; /* buffer2 */
176
double reset_buffer2;/* reset value of buffer2 */
177
} sinus_modulator;
178
179
/*-----------------------------------------------------------------------------
180
Triangle modulator
181
-----------------------------------------------------------------------------*/
182
typedef struct
183
{
184
fluid_real_t freq; /* Osc. Frequency (in Hertz) */
185
fluid_real_t val; /* internal current value */
186
fluid_real_t inc; /* increment value */
187
} triang_modulator;
188
189
/*-----------------------------------------------------------------------------
190
modulator
191
-----------------------------------------------------------------------------*/
192
typedef struct
193
{
194
/*-------------*/
195
int line_out; /* current line out position for this modulator */
196
/*-------------*/
197
sinus_modulator sinus; /* sinus lfo */
198
triang_modulator triang; /* triangle lfo */
199
/*-------------------------*/
200
/* first order All-Pass interpolator members */
201
fluid_real_t frac_pos_mod; /* fractional position part between samples */
202
/* previous value used when interpolating using fractional */
203
fluid_real_t buffer;
204
} modulator;
205
206
/* Private data for SKEL file */
207
struct _fluid_chorus_t
208
{
209
int type;
210
fluid_real_t depth_ms;
211
fluid_real_t level;
212
fluid_real_t speed_Hz;
213
int number_blocks;
214
fluid_real_t sample_rate;
215
216
/* width control: 0 monophonic, > 0 more stereophonic */
217
fluid_real_t width;
218
fluid_real_t wet1, wet2;
219
220
fluid_real_t *line; /* buffer line */
221
int size; /* effective internal size (in samples) */
222
223
int line_in; /* line in position */
224
225
/* center output position members */
226
fluid_real_t center_pos_mod; /* center output position modulated by modulator */
227
int mod_depth; /* modulation depth (in samples) */
228
229
/* variable rate control of center output position */
230
int index_rate; /* index rate to know when to update center_pos_mod */
231
int mod_rate; /* rate at which center_pos_mod is updated */
232
233
/* modulator member */
234
modulator mod[MAX_CHORUS]; /* sinus/triangle modulator */
235
};
236
237
/*-----------------------------------------------------------------------------
238
Sets the frequency of sinus oscillator.
239
240
For sufficient precision use double precision in set_sinus_frequency() computation !.
241
Never use: fluid_real_t , cosf(), sinf(), FLUID_COS(), FLUID_SIN(), FLUID_M_PI.
242
See https://github.com/FluidSynth/fluidsynth/issues/1331
243
244
@param mod pointer on modulator structure.
245
@param freq frequency of the oscillator in Hz.
246
@param sample_rate sample rate on audio output in Hz.
247
@param phase initial phase of the oscillator in degree (0 to 360).
248
-----------------------------------------------------------------------------*/
249
static void set_sinus_frequency(sinus_modulator *mod,
250
float freq, float sample_rate, float phase)
251
{
252
double w = (2.0 * M_PI) * freq / sample_rate; /* step phase between each sinus wave sample (in radian) */
253
double a; /* initial phase at which the sinus wave must begin (in radian) */
254
255
// DO NOT use potentially single precision cosf or FLUID_COS here! See https://github.com/FluidSynth/fluidsynth/issues/1331
256
mod->a1 = 2 * cos(w);
257
258
a = (2.0 * M_PI / 360.0) * phase;
259
260
mod->buffer2 = sin(a - w); /* y(n-1) = sin(-initial angle) */
261
mod->buffer1 = sin(a); /* y(n) = sin(initial phase) */
262
mod->reset_buffer2 = sin((M_PI / 2.0) - w); /* reset value for PI/2 */
263
}
264
265
/*-----------------------------------------------------------------------------
266
Gets current value of sinus modulator:
267
y(n) = a1 . y(n-1) - y(n-2)
268
out = a1 . buffer1 - buffer2
269
270
@param mod pointer on modulator structure.
271
@return current value of the modulator sine wave.
272
-----------------------------------------------------------------------------*/
273
static FLUID_INLINE double get_mod_sinus(sinus_modulator *mod)
274
{
275
double out;
276
out = mod->a1 * mod->buffer1 - mod->buffer2;
277
mod->buffer2 = mod->buffer1;
278
279
if(out >= 1.0) /* reset in case of instability near PI/2 */
280
{
281
out = 1.0; /* forces output to the right value */
282
mod->buffer2 = mod->reset_buffer2;
283
}
284
285
if(out <= -1.0) /* reset in case of instability near -PI/2 */
286
{
287
out = -1.0; /* forces output to the right value */
288
mod->buffer2 = - mod->reset_buffer2;
289
}
290
291
mod->buffer1 = out;
292
return out;
293
}
294
295
/*-----------------------------------------------------------------------------
296
Set the frequency of triangular oscillator
297
The frequency is converted in a slope value.
298
The initial value is set according to frac_phase which is a position
299
in the period relative to the beginning of the period.
300
For example: 0 is the beginning of the period, 1/4 is at 1/4 of the period
301
relative to the beginning.
302
303
@param mod pointer on modulator structure.
304
@param freq frequency of the oscillator in Hz.
305
@param sample_rate sample rate on audio output in Hz.
306
@param frac_phase initial phase (see comment above).
307
-----------------------------------------------------------------------------*/
308
static void set_triangle_frequency(triang_modulator *mod, float freq,
309
float sample_rate, float frac_phase)
310
{
311
fluid_real_t ns_period; /* period in numbers of sample */
312
313
if(freq <= 0.0)
314
{
315
freq = 0.5f;
316
}
317
318
mod->freq = freq;
319
320
ns_period = sample_rate / freq;
321
322
/* the slope of a triangular osc (0 up to +1 down to -1 up to 0....) is equivalent
323
to the slope of a saw osc (0 -> +4) */
324
mod->inc = 4 / ns_period; /* positive slope */
325
326
/* The initial value and the sign of the slope depend of initial phase:
327
initial value = = (ns_period * frac_phase) * slope
328
*/
329
mod->val = ns_period * frac_phase * mod->inc;
330
331
if(1.0 <= mod->val && mod->val < 3.0)
332
{
333
mod->val = 2.0 - mod->val; /* 1.0 down to -1.0 */
334
mod->inc = -mod->inc; /* negative slope */
335
}
336
else if(3.0 <= mod->val)
337
{
338
mod->val = mod->val - 4.0; /* -1.0 up to +1.0. */
339
}
340
341
/* else val < 1.0 */
342
}
343
344
/*-----------------------------------------------------------------------------
345
Get current value of triangular oscillator
346
y(n) = y(n-1) + dy
347
348
@param mod pointer on triang_modulator structure.
349
@return current value.
350
-----------------------------------------------------------------------------*/
351
static FLUID_INLINE fluid_real_t get_mod_triang(triang_modulator *mod)
352
{
353
mod->val = mod->val + mod->inc ;
354
355
if(mod->val >= 1.0)
356
{
357
mod->inc = -mod->inc;
358
return 1.0;
359
}
360
361
if(mod->val <= -1.0)
362
{
363
mod->inc = -mod->inc;
364
return -1.0;
365
}
366
367
return mod->val;
368
}
369
/*-----------------------------------------------------------------------------
370
Reads the sample value out of the modulated delay line.
371
372
@param chorus pointer on chorus unit.
373
@param mod pointer on modulator structure.
374
@return current value.
375
-----------------------------------------------------------------------------*/
376
static FLUID_INLINE fluid_real_t get_mod_delay(fluid_chorus_t *chorus,
377
modulator *mod)
378
{
379
fluid_real_t out_index; /* new modulated index position */
380
int int_out_index; /* integer part of out_index */
381
fluid_real_t out; /* value to return */
382
383
/* Checks if the modulator must be updated (every mod_rate samples). */
384
/* Important: center_pos_mod must be used immediately for the
385
first sample. So, mdl->index_rate must be initialized
386
to mdl->mod_rate (new_mod_delay_line()) */
387
388
if(chorus->index_rate >= chorus->mod_rate)
389
{
390
/* out_index = center position (center_pos_mod) + sinus waweform */
391
if(chorus->type == FLUID_CHORUS_MOD_SINE)
392
{
393
out_index = chorus->center_pos_mod +
394
get_mod_sinus(&mod->sinus) * chorus->mod_depth;
395
}
396
else
397
{
398
out_index = chorus->center_pos_mod +
399
get_mod_triang(&mod->triang) * chorus->mod_depth;
400
}
401
402
/* extracts integer part in int_out_index */
403
if(out_index >= 0.0f)
404
{
405
int_out_index = (int)out_index; /* current integer part */
406
407
/* forces read index (line_out) with integer modulation value */
408
/* Boundary check and circular motion as needed */
409
if((mod->line_out = int_out_index) >= chorus->size)
410
{
411
mod->line_out -= chorus->size;
412
}
413
}
414
else /* negative */
415
{
416
int_out_index = (int)(out_index - 1); /* previous integer part */
417
/* forces read index (line_out) with integer modulation value */
418
/* circular motion as needed */
419
mod->line_out = int_out_index + chorus->size;
420
}
421
422
/* extracts fractionnal part. (it will be used when interpolating
423
between line_out and line_out +1) and memorize it.
424
Memorizing is necessary for modulation rate above 1 */
425
mod->frac_pos_mod = out_index - int_out_index;
426
}
427
428
/* First order all-pass interpolation ----------------------------------*/
429
/* https://ccrma.stanford.edu/~jos/pasp/First_Order_Allpass_Interpolation.html */
430
/* begins interpolation: read current sample */
431
out = chorus->line[mod->line_out];
432
433
/* updates line_out to the next sample.
434
Boundary check and circular motion as needed */
435
if(++mod->line_out >= chorus->size)
436
{
437
mod->line_out -= chorus->size;
438
}
439
440
/* Fractional interpolation between next sample (at next position) and
441
previous output added to current sample.
442
*/
443
out += mod->frac_pos_mod * (chorus->line[mod->line_out] - mod->buffer);
444
mod->buffer = out; /* memorizes current output */
445
return out;
446
}
447
448
/*-----------------------------------------------------------------------------
449
Push a sample val into the delay line
450
451
@param dl delay line to push value into.
452
@param val the value to push into dl.
453
-----------------------------------------------------------------------------*/
454
#define push_in_delay_line(dl, val) \
455
{\
456
dl->line[dl->line_in] = val;\
457
/* Incrementation and circular motion if necessary */\
458
if(++dl->line_in >= dl->size) dl->line_in -= dl->size;\
459
}\
460
461
/*-----------------------------------------------------------------------------
462
Initialize : mod_rate, center_pos_mod, and index rate
463
464
center_pos_mod is initialized so that the delay between center_pos_mod and
465
line_in is: mod_depth + INTERP_SAMPLES_NBR.
466
467
@param chorus pointer on chorus unit.
468
-----------------------------------------------------------------------------*/
469
static void set_center_position(fluid_chorus_t *chorus)
470
{
471
int center;
472
473
/* Sets the modulation rate. This rate defines how often
474
the center position (center_pos_mod ) is modulated .
475
The value is expressed in samples. The default value is 1 that means that
476
center_pos_mod is updated at every sample.
477
For example with a value of 2, the center position position will be
478
updated only one time every 2 samples only.
479
*/
480
chorus->mod_rate = LOW_MOD_RATE; /* default modulation rate */
481
482
/* compensate mod rate for high modulation depth */
483
if(chorus->mod_depth > LOW_MOD_DEPTH)
484
{
485
int delta_mod_depth = (chorus->mod_depth - LOW_MOD_DEPTH);
486
chorus->mod_rate += (delta_mod_depth * RANGE_MOD_RATE) / RANGE_MOD_DEPTH;
487
}
488
489
/* Initializes the modulated center position (center_pos_mod) so that:
490
- the delay between center_pos_mod and line_in is:
491
mod_depth + INTERP_SAMPLES_NBR.
492
*/
493
center = chorus->line_in - (INTERP_SAMPLES_NBR + chorus->mod_depth);
494
495
if(center < 0)
496
{
497
center += chorus->size;
498
}
499
500
chorus->center_pos_mod = (fluid_real_t)center;
501
502
/* index rate to control when to update center_pos_mod */
503
/* Important: must be set to get center_pos_mod immediately used for the
504
reading of first sample (see get_mod_delay()) */
505
chorus->index_rate = chorus->mod_rate;
506
}
507
508
/*-----------------------------------------------------------------------------
509
Update internal parameters dependent of sample rate.
510
- mod_depth.
511
- mod_rate, center_pos_mod, and index rate.
512
- modulators frequency.
513
514
@param chorus, pointer on chorus unit.
515
-----------------------------------------------------------------------------*/
516
static void update_parameters_from_sample_rate(fluid_chorus_t *chorus)
517
{
518
int i;
519
520
/* initialize modulation depth (peak to peak) (in samples) */
521
/* convert modulation depth in ms to sample number */
522
chorus->mod_depth = (int)(chorus->depth_ms / 1000.0
523
* chorus->sample_rate);
524
525
/* the delay line is fixed. So we reduce mod_depth (if necessary) */
526
if(chorus->mod_depth > MAX_SAMPLES)
527
{
528
FLUID_LOG(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).",
529
MAX_SAMPLES);
530
chorus->mod_depth = MAX_SAMPLES;
531
/* set depth_ms to maximum to avoid spamming console with above warning */
532
chorus->depth_ms = (chorus->mod_depth * 1000) / chorus->sample_rate;
533
}
534
535
chorus->mod_depth /= 2; /* amplitude is peak to peek / 2 */
536
#ifdef DEBUG_PRINT
537
printf("depth_ms:%f, depth_samples/2:%d\n", chorus->depth_ms, chorus->mod_depth);
538
#endif
539
540
/* Initializes the modulated center position:
541
mod_rate, center_pos_mod, and index rate.
542
*/
543
set_center_position(chorus); /* must be called before set_xxxx_frequency() */
544
#ifdef DEBUG_PRINT
545
printf("mod_rate:%d\n", chorus->mod_rate);
546
#endif
547
548
/* initialize modulator frequency */
549
for(i = 0; i < chorus->number_blocks; i++)
550
{
551
set_sinus_frequency(&chorus->mod[i].sinus,
552
chorus->speed_Hz * chorus->mod_rate,
553
chorus->sample_rate,
554
/* phase offset between modulators waveform */
555
(float)((360.0f / (float) chorus->number_blocks) * i));
556
557
set_triangle_frequency(&chorus->mod[i].triang,
558
chorus->speed_Hz * chorus->mod_rate,
559
chorus->sample_rate,
560
/* phase offset between modulators waveform */
561
(float)i / chorus->number_blocks);
562
}
563
}
564
565
/*-----------------------------------------------------------------------------
566
Modulated delay line initialization.
567
568
Sets the length line ( alloc delay samples).
569
Remark: the function sets the internal size according to the length delay_length.
570
The size is augmented by INTERP_SAMPLES_NBR to take account of interpolation.
571
572
@param chorus, pointer on chorus unit.
573
@param delay_length the length of the delay line in samples.
574
@return FLUID_OK if success , FLUID_FAILED if memory error.
575
576
Return FLUID_OK if success, FLUID_FAILED if memory error.
577
-----------------------------------------------------------------------------*/
578
static int new_mod_delay_line(fluid_chorus_t *chorus, int delay_length)
579
{
580
/*-----------------------------------------------------------------------*/
581
/* checks parameter */
582
if(delay_length < 1)
583
{
584
return FLUID_FAILED;
585
}
586
587
chorus->mod_depth = 0;
588
/*-----------------------------------------------------------------------
589
allocates delay_line and initialize members: - line, size, line_in...
590
*/
591
/* total size of the line: size = INTERP_SAMPLES_NBR + delay_length */
592
chorus->size = delay_length + INTERP_SAMPLES_NBR;
593
chorus->line = FLUID_ARRAY(fluid_real_t, chorus->size);
594
595
if(! chorus->line)
596
{
597
return FLUID_FAILED;
598
}
599
600
/* clears the buffer:
601
- delay line
602
- interpolator member: buffer, frac_pos_mod
603
*/
604
fluid_chorus_reset(chorus);
605
606
/* Initializes line_in to the start of the buffer */
607
chorus->line_in = 0;
608
/*------------------------------------------------------------------------
609
Initializes modulation members:
610
- modulation rate (the speed at which center_pos_mod is modulated: mod_rate
611
- modulated center position: center_pos_mod
612
- index rate to know when to update center_pos_mod:index_rate
613
-------------------------------------------------------------------------*/
614
/* Initializes the modulated center position:
615
mod_rate, center_pos_mod, and index rate
616
*/
617
set_center_position(chorus);
618
619
return FLUID_OK;
620
}
621
622
/*-----------------------------------------------------------------------------
623
API
624
------------------------------------------------------------------------------*/
625
/**
626
* Create the chorus unit. Once created the chorus have no parameters set, so
627
* fluid_chorus_set() must be called at least one time after calling
628
* new_fluid_chorus().
629
*
630
* @param sample_rate, audio sample rate in Hz.
631
* @return pointer on chorus unit.
632
*/
633
fluid_chorus_t *
634
new_fluid_chorus(fluid_real_t sample_rate)
635
{
636
fluid_chorus_t *chorus;
637
638
chorus = FLUID_NEW(fluid_chorus_t);
639
640
if(chorus == NULL)
641
{
642
FLUID_LOG(FLUID_PANIC, "chorus: Out of memory");
643
return NULL;
644
}
645
646
FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t));
647
648
chorus->sample_rate = sample_rate;
649
650
#ifdef DEBUG_PRINT
651
printf("fluid_chorus_t:%d bytes\n", sizeof(fluid_chorus_t));
652
printf("fluid_real_t:%d bytes\n", sizeof(fluid_real_t));
653
#endif
654
655
#ifdef DEBUG_PRINT
656
printf("NEW_MOD\n");
657
#endif
658
659
if(new_mod_delay_line(chorus, MAX_SAMPLES) == FLUID_FAILED)
660
{
661
delete_fluid_chorus(chorus);
662
return NULL;
663
}
664
665
return chorus;
666
}
667
668
/**
669
* Delete the chorus unit.
670
* @param chorus pointer on chorus unit returned by new_fluid_chorus().
671
*/
672
void
673
delete_fluid_chorus(fluid_chorus_t *chorus)
674
{
675
fluid_return_if_fail(chorus != NULL);
676
677
FLUID_FREE(chorus->line);
678
FLUID_FREE(chorus);
679
}
680
681
/**
682
* Clear the internal delay line and associate filter.
683
* @param chorus pointer on chorus unit returned by new_fluid_chorus().
684
*/
685
void
686
fluid_chorus_reset(fluid_chorus_t *chorus)
687
{
688
int i;
689
unsigned int u;
690
691
/* reset delay line */
692
for(i = 0; i < chorus->size; i++)
693
{
694
chorus->line[i] = 0;
695
}
696
697
/* reset modulators's allpass filter */
698
for(u = 0; u < FLUID_N_ELEMENTS(chorus->mod); u++)
699
{
700
/* initializes 1st order All-Pass interpolator members */
701
chorus->mod[u].buffer = 0; /* previous delay sample value */
702
chorus->mod[u].frac_pos_mod = 0; /* fractional position (between consecutives sample) */
703
}
704
}
705
706
/**
707
* Set one or more chorus parameters.
708
*
709
* @param chorus Chorus instance.
710
* @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t).
711
* @param nr Chorus voice count (0-99, CPU time consumption proportional to
712
* this value).
713
* @param level Chorus level (0.0-10.0).
714
* @param speed Chorus speed in Hz (0.1-5.0).
715
* @param depth_ms Chorus depth (max value depends on synth sample rate,
716
* 0.0-21.0 is safe for sample rate values up to 96KHz).
717
* @param type Chorus waveform type (#fluid_chorus_mod).
718
*/
719
void
720
fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level,
721
fluid_real_t speed, fluid_real_t depth_ms, int type)
722
{
723
if(set & FLUID_CHORUS_SET_NR) /* number of block */
724
{
725
chorus->number_blocks = nr;
726
}
727
728
if(set & FLUID_CHORUS_SET_LEVEL) /* output level */
729
{
730
chorus->level = level;
731
}
732
733
if(set & FLUID_CHORUS_SET_SPEED) /* lfo frequency (in Hz) */
734
{
735
chorus->speed_Hz = speed;
736
}
737
738
if(set & FLUID_CHORUS_SET_DEPTH) /* modulation depth (in ms) */
739
{
740
chorus->depth_ms = depth_ms;
741
}
742
743
if(set & FLUID_CHORUS_SET_TYPE) /* lfo shape (sinus, triangle) */
744
{
745
chorus->type = type;
746
}
747
748
/* check min , max parameters */
749
if(chorus->number_blocks < 0)
750
{
751
FLUID_LOG(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0.");
752
chorus->number_blocks = 0;
753
}
754
else if(chorus->number_blocks > MAX_CHORUS)
755
{
756
FLUID_LOG(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.",
757
MAX_CHORUS);
758
chorus->number_blocks = MAX_CHORUS;
759
}
760
761
if(chorus->speed_Hz < MIN_SPEED_HZ)
762
{
763
FLUID_LOG(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.",
764
(double) MIN_SPEED_HZ);
765
chorus->speed_Hz = MIN_SPEED_HZ;
766
}
767
else if(chorus->speed_Hz > MAX_SPEED_HZ)
768
{
769
FLUID_LOG(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.",
770
(double) MAX_SPEED_HZ);
771
chorus->speed_Hz = MAX_SPEED_HZ;
772
}
773
774
if(chorus->depth_ms < 0.0)
775
{
776
FLUID_LOG(FLUID_WARN, "chorus: depth must be positive! Setting value to 0.");
777
chorus->depth_ms = 0.0;
778
}
779
780
if(chorus->level < 0.0)
781
{
782
FLUID_LOG(FLUID_WARN, "chorus: level must be positive! Setting value to 0.");
783
chorus->level = 0.0;
784
}
785
else if(chorus->level > MAX_LEVEL)
786
{
787
FLUID_LOG(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! "
788
"Setting it to 0.1.");
789
chorus->level = 0.1;
790
}
791
792
/* update parameters dependent of sample rate */
793
update_parameters_from_sample_rate(chorus);
794
795
#ifdef DEBUG_PRINT
796
printf("lfo type:%d\n", chorus->type);
797
printf("speed_Hz:%f\n", chorus->speed_Hz);
798
#endif
799
800
/* Initialize the lfo waveform */
801
if((chorus->type != FLUID_CHORUS_MOD_SINE) &&
802
(chorus->type != FLUID_CHORUS_MOD_TRIANGLE))
803
{
804
FLUID_LOG(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave.");
805
chorus->type = FLUID_CHORUS_MOD_SINE;
806
}
807
808
#ifdef DEBUG_PRINT
809
810
if(chorus->type == FLUID_CHORUS_MOD_SINE)
811
{
812
printf("lfo: sinus\n");
813
}
814
else
815
{
816
printf("lfo: triangle\n");
817
}
818
819
printf("nr:%d\n", chorus->number_blocks);
820
#endif
821
822
/* Recalculate internal values after parameters change */
823
824
/*
825
Note:
826
Actually WIDTH is fixed to maximum value. But in the future we could add a setting
827
"synth.chorus.width" to allow a gradually stereo effect from minimum (monophonic) to
828
maximum stereo effect.
829
If this setting will be added, remove the following instruction.
830
*/
831
chorus->width = WIDTH;
832
{
833
/* The stereo amplitude equation (wet1 and wet2 below) have a
834
tendency to produce high amplitude with high width values ( 1 < width < 10).
835
This results in an unwanted noisy output clipped by the audio card.
836
To avoid this dependency, we divide by (1 + chorus->width * SCALE_WET_WIDTH)
837
Actually, with a SCALE_WET_WIDTH of 0.2, (regardless of level setting),
838
the output amplitude (wet) seems rather independent of width setting */
839
840
fluid_real_t wet = chorus->level * SCALE_WET ;
841
842
/* wet1 and wet2 are used by the stereo effect controlled by the width setting
843
for producing a stereo ouptput from a monophonic chorus signal.
844
Please see the note above about a side effect tendency */
845
846
if(chorus->number_blocks > 1)
847
{
848
wet = wet / (1.0f + chorus->width * SCALE_WET_WIDTH);
849
chorus->wet1 = wet * (chorus->width / 2.0f + 0.5f);
850
chorus->wet2 = wet * ((1.0f - chorus->width) / 2.0f);
851
#ifdef DEBUG_PRINT
852
printf("width:%f\n", chorus->width);
853
854
if(chorus->width > 0)
855
{
856
printf("nr > 1, width > 0 => out stereo\n");
857
}
858
else
859
{
860
printf("nr > 1, width:0 =>out mono\n");
861
}
862
863
#endif
864
}
865
else
866
{
867
/* only one chorus block */
868
if(chorus->width == 0.0)
869
{
870
/* wet1 and wet2 should make stereo output monomophic */
871
chorus->wet1 = chorus->wet2 = wet;
872
}
873
else
874
{
875
/* for width > 0, wet1 and wet2 should make stereo output stereo
876
with only one block. This will only possible by inverting
877
the unique signal on each left and right output.
878
Note however that with only one block, it isn't possible to
879
have a graduate width effect */
880
chorus->wet1 = wet;
881
chorus->wet2 = -wet; /* inversion */
882
}
883
884
#ifdef DEBUG_PRINT
885
printf("width:%f\n", chorus->width);
886
887
if(chorus->width != 0)
888
{
889
printf("one block, width > 0 => out stereo\n");
890
}
891
else
892
{
893
printf("one block, width:0 => out mono\n");
894
}
895
896
#endif
897
}
898
}
899
}
900
901
/*
902
* Applies a sample rate change on the chorus.
903
* Note that while the chorus is used by calling any fluid_chorus_processXXX()
904
* function, calling fluid_chorus_samplerate_change() isn't multi task safe.
905
* To deal properly with this issue follow the steps:
906
* 1) Stop chorus processing (i.e disable calling to any fluid_chorus_processXXX().
907
* chorus functions.
908
* 2) Change sample rate by calling fluid_chorus_samplerate_change().
909
* 3) Restart chorus processing (i.e enabling calling any fluid_chorus_processXXX()
910
* chorus functions.
911
*
912
* Another solution is to substitute step (2):
913
* 2.1) delete the chorus by calling delete_fluid_chorus().
914
* 2.2) create the chorus by calling new_fluid_chorus().
915
*
916
* @param chorus pointer on the chorus.
917
* @param sample_rate new sample rate value.
918
*/
919
void
920
fluid_chorus_samplerate_change(fluid_chorus_t *chorus, fluid_real_t sample_rate)
921
{
922
chorus->sample_rate = sample_rate;
923
924
/* update parameters dependent of sample rate */
925
update_parameters_from_sample_rate(chorus);
926
}
927
928
/**
929
* Process chorus by mixing the result in output buffer.
930
* @param chorus pointer on chorus unit returned by new_fluid_chorus().
931
* @param in, pointer on monophonic input buffer of FLUID_BUFSIZE samples.
932
* @param left_out, right_out, pointers on stereo output buffers of
933
* FLUID_BUFSIZE samples.
934
*/
935
void fluid_chorus_processmix(fluid_chorus_t *chorus, const fluid_real_t *in,
936
fluid_real_t *left_out, fluid_real_t *right_out)
937
{
938
int sample_index;
939
int i;
940
fluid_real_t d_out[2]; /* output stereo Left and Right */
941
942
/* foreach sample, process output sample then input sample */
943
for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++)
944
{
945
fluid_real_t out; /* block output */
946
947
d_out[0] = d_out[1] = 0.0f; /* clear stereo unit input */
948
949
#if 0
950
/* Debug: Listen to the chorus signal only */
951
left_out[sample_index] = 0;
952
right_out[sample_index] = 0;
953
#endif
954
955
++chorus->index_rate; /* modulator rate */
956
957
/* foreach chorus block, process output sample */
958
for(i = 0; i < chorus->number_blocks; i++)
959
{
960
/* get sample from the output of modulated delay line */
961
out = get_mod_delay(chorus, &chorus->mod[i]);
962
963
/* accumulate out into stereo unit input */
964
d_out[i & 1] += out;
965
}
966
967
/* update modulator index rate and output center position */
968
if(chorus->index_rate >= chorus->mod_rate)
969
{
970
chorus->index_rate = 0; /* clear modulator index rate */
971
972
/* updates center position (center_pos_mod) to the next position
973
specified by modulation rate */
974
if((chorus->center_pos_mod += chorus->mod_rate) >= chorus->size)
975
{
976
chorus->center_pos_mod -= chorus->size;
977
}
978
}
979
980
/* Adjust stereo input level in case of number_blocks odd:
981
In those case, d_out[1] level is lower than d_out[0], so we need to
982
add out value to d_out[1] to have d_out[0] and d_out[1] balanced.
983
*/
984
if((i & 1) && i > 2) // i = 3,5,7...
985
{
986
d_out[1] += out ;
987
}
988
989
/* Write the current input sample into the circular buffer.
990
* Note that 'in' may be aliased with 'left_out'. Hence this must be done
991
* before "processing stereo unit" (below). This ensures input buffer
992
* not being overwritten by stereo unit output.
993
*/
994
push_in_delay_line(chorus, in[sample_index]);
995
996
/* process stereo unit */
997
/* Add the chorus stereo unit d_out to left and right output */
998
left_out[sample_index] += d_out[0] * chorus->wet1 + d_out[1] * chorus->wet2;
999
right_out[sample_index] += d_out[1] * chorus->wet1 + d_out[0] * chorus->wet2;
1000
}
1001
}
1002
1003
/**
1004
* Process chorus by putting the result in output buffer (no mixing).
1005
* @param chorus pointer on chorus unit returned by new_fluid_chorus().
1006
* @param in, pointer on monophonic input buffer of FLUID_BUFSIZE samples.
1007
* @param left_out, right_out, pointers on stereo output buffers of
1008
* FLUID_BUFSIZE samples.
1009
*/
1010
/* Duplication of code ... (replaces sample data instead of mixing) */
1011
void fluid_chorus_processreplace(fluid_chorus_t *chorus, const fluid_real_t *in,
1012
fluid_real_t *left_out, fluid_real_t *right_out)
1013
{
1014
int sample_index;
1015
int i;
1016
fluid_real_t d_out[2]; /* output stereo Left and Right */
1017
1018
/* foreach sample, process output sample then input sample */
1019
for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++)
1020
{
1021
fluid_real_t out; /* block output */
1022
1023
d_out[0] = d_out[1] = 0.0f; /* clear stereo unit input */
1024
1025
#if 0
1026
/* Debug: Listen to the chorus signal only */
1027
left_out[sample_index] = 0;
1028
right_out[sample_index] = 0;
1029
#endif
1030
1031
++chorus->index_rate; /* modulator rate */
1032
1033
/* foreach chorus block, process output sample */
1034
for(i = 0; i < chorus->number_blocks; i++)
1035
{
1036
/* get sample from the output of modulated delay line */
1037
out = get_mod_delay(chorus, &chorus->mod[i]);
1038
1039
/* accumulate out into stereo unit input */
1040
d_out[i & 1] += out;
1041
}
1042
1043
/* update modulator index rate and output center position */
1044
if(chorus->index_rate >= chorus->mod_rate)
1045
{
1046
chorus->index_rate = 0; /* clear modulator index rate */
1047
1048
/* updates center position (center_pos_mod) to the next position
1049
specified by modulation rate */
1050
if((chorus->center_pos_mod += chorus->mod_rate) >= chorus->size)
1051
{
1052
chorus->center_pos_mod -= chorus->size;
1053
}
1054
}
1055
1056
/* Adjust stereo input level in case of number_blocks odd:
1057
In those case, d_out[1] level is lower than d_out[0], so we need to
1058
add out value to d_out[1] to have d_out[0] and d_out[1] balanced.
1059
*/
1060
if((i & 1) && i > 2) // i = 3,5,7...
1061
{
1062
d_out[1] += out ;
1063
}
1064
1065
/* Write the current input sample into the circular buffer.
1066
* Note that 'in' may be aliased with 'left_out'. Hence this must be done
1067
* before "processing stereo unit" (below). This ensures input buffer
1068
* not being overwritten by stereo unit output.
1069
*/
1070
push_in_delay_line(chorus, in[sample_index]);
1071
1072
/* process stereo unit */
1073
/* store the chorus stereo unit d_out to left and right output */
1074
left_out[sample_index] = d_out[0] * chorus->wet1 + d_out[1] * chorus->wet2;
1075
right_out[sample_index] = d_out[1] * chorus->wet1 + d_out[0] * chorus->wet2;
1076
}
1077
}
1078
1079