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