1 /*---------------------------------------------------------------------------- 2 * 3 * File: 4 * eas_reverbdata.h 5 * 6 * Contents and purpose: 7 * Contains the prototypes for the Reverb effect. 8 * 9 * 10 * Copyright Sonic Network Inc. 2006 11 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 * 24 *---------------------------------------------------------------------------- 25 * Revision Control: 26 * $Revision: 499 $ 27 * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ 28 *---------------------------------------------------------------------------- 29 */ 30 31 #ifndef _EAS_REVERBDATA_H 32 #define _EAS_REVERBDATA_H 33 34 #include "eas_types.h" 35 #include "eas_audioconst.h" 36 37 /*------------------------------------ 38 * defines 39 *------------------------------------ 40 */ 41 42 /* 43 CIRCULAR() calculates the array index using modulo arithmetic. 44 The "trick" is that modulo arithmetic is simplified by masking 45 the effective address where the mask is (2^n)-1. This only works 46 if the buffer size is a power of two. 47 */ 48 #define CIRCULAR(base,offset,size) (EAS_U32)( \ 49 ( \ 50 ((EAS_I32)(base)) + ((EAS_I32)(offset)) \ 51 ) \ 52 & size \ 53 ) 54 55 /* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */ 56 #if defined (_SAMPLE_RATE_8000) 57 58 #define REVERB_UPDATE_PERIOD_IN_BITS 5 59 #define REVERB_BUFFER_SIZE_IN_SAMPLES 2048 60 61 #elif defined (_SAMPLE_RATE_16000) 62 63 #define REVERB_UPDATE_PERIOD_IN_BITS 6 64 #define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 65 66 #elif defined (_SAMPLE_RATE_22050) 67 68 #define REVERB_UPDATE_PERIOD_IN_BITS 7 69 #define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 70 71 #elif defined (_SAMPLE_RATE_32000) 72 73 #define REVERB_UPDATE_PERIOD_IN_BITS 7 74 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 75 76 #elif defined (_SAMPLE_RATE_44100) 77 78 #define REVERB_UPDATE_PERIOD_IN_BITS 8 79 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 80 81 #elif defined (_SAMPLE_RATE_48000) 82 83 #define REVERB_UPDATE_PERIOD_IN_BITS 8 84 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 85 86 #endif 87 88 // Define a mask for circular addressing, so that array index 89 // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) 90 // The buffer size MUST be a power of two 91 #define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1) 92 93 #define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid 94 #define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel 95 96 /* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ 97 #define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS) 98 99 /* 100 calculate the update counter by bitwise ANDING with this value to 101 generate a 2^n modulo value 102 */ 103 #define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1) 104 105 /* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */ 106 #define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE) 107 108 // xfade parameters 109 #define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds 110 111 #define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE) 112 113 #define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES)) 114 115 /**********/ 116 /* the entire synth uses various flags in a bit field */ 117 118 /* if flag is set, synth reset has been requested */ 119 #define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ 120 #define MASK_REVERB_RESET_IS_REQUESTED 0x01 121 #define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED) 122 123 /* 124 by default, we always want to update ALL channel parameters 125 when we reset the synth (e.g., during GM ON) 126 */ 127 #define DEFAULT_REVERB_FLAGS 0x0 128 129 /* coefficients for generating sin, cos */ 130 #define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ 131 /* 132 EAS_I32 nPanG1 = +1.0 for sin 133 EAS_I32 nPanG1 = -1.0 for cos 134 */ 135 #define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ 136 137 /*************************************************************/ 138 // define the input injection points 139 #define GUARD 5 // safety guard of this many samples 140 141 #define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds 142 #define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds 143 144 #define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) 145 #define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) 146 147 #define AP0_IN 0 148 #define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD) 149 #define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD) 150 #define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD) 151 152 // Define the max offsets for the end points of each section 153 // i.e., we don't expect a given section's taps to go beyond 154 // the following limits 155 #define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1) 156 #define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1) 157 #define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1) 158 #define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1) 159 160 #define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number 161 #define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) 162 #define DEFAULT_AP0_GAIN 19400 163 #define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) 164 #define DEFAULT_AP1_GAIN -19400 165 166 #define REVERB_DEFAULT_WET 32767 167 #define REVERB_DEFAULT_DRY 0 168 169 #define EAS_REVERB_WET_MAX 32767 170 #define EAS_REVERB_WET_MIN 0 171 #define EAS_REVERB_DRY_MAX 32767 172 #define EAS_REVERB_DRY_MIN 0 173 174 /* parameters for each allpass */ 175 typedef struct 176 { 177 EAS_U16 m_zApOut; // delay offset for ap out 178 179 EAS_I16 m_nApGain; // gain for ap 180 181 EAS_U16 m_zApIn; // delay offset for ap in 182 183 } S_ALLPASS_OBJECT; 184 185 186 /* parameters for each allpass */ 187 typedef struct 188 { 189 EAS_PCM m_zLpf; // actual state variable, not a length 190 191 EAS_I16 m_nLpfFwd; // lpf forward gain 192 193 EAS_I16 m_nLpfFbk; // lpf feedback gain 194 195 EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out 196 197 EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap 198 199 } S_EARLY_REFLECTION_OBJECT; 200 201 //demo 202 typedef struct 203 { 204 EAS_I16 m_nLpfFbk; 205 EAS_I16 m_nLpfFwd; 206 207 EAS_I16 m_nEarly; 208 EAS_I16 m_nWet; 209 EAS_I16 m_nDry; 210 211 EAS_I16 m_nEarlyL_LpfFbk; 212 EAS_I16 m_nEarlyL_LpfFwd; 213 214 EAS_I16 m_nEarlyL_Delay0; //8 215 EAS_I16 m_nEarlyL_Gain0; 216 EAS_I16 m_nEarlyL_Delay1; 217 EAS_I16 m_nEarlyL_Gain1; 218 EAS_I16 m_nEarlyL_Delay2; 219 EAS_I16 m_nEarlyL_Gain2; 220 EAS_I16 m_nEarlyL_Delay3; 221 EAS_I16 m_nEarlyL_Gain3; 222 EAS_I16 m_nEarlyL_Delay4; 223 EAS_I16 m_nEarlyL_Gain4; 224 225 EAS_I16 m_nEarlyR_Delay0; //18 226 EAS_I16 m_nEarlyR_Gain0; 227 EAS_I16 m_nEarlyR_Delay1; 228 EAS_I16 m_nEarlyR_Gain1; 229 EAS_I16 m_nEarlyR_Delay2; 230 EAS_I16 m_nEarlyR_Gain2; 231 EAS_I16 m_nEarlyR_Delay3; 232 EAS_I16 m_nEarlyR_Gain3; 233 EAS_I16 m_nEarlyR_Delay4; 234 EAS_I16 m_nEarlyR_Gain4; 235 236 EAS_U16 m_nMaxExcursion; //28 237 EAS_I16 m_nXfadeInterval; 238 239 EAS_I16 m_nAp0_ApGain; //30 240 EAS_I16 m_nAp0_ApOut; 241 EAS_I16 m_nAp1_ApGain; 242 EAS_I16 m_nAp1_ApOut; 243 244 EAS_I16 m_rfu4; 245 EAS_I16 m_rfu5; 246 EAS_I16 m_rfu6; 247 EAS_I16 m_rfu7; 248 EAS_I16 m_rfu8; 249 EAS_I16 m_rfu9; 250 EAS_I16 m_rfu10; //43 251 252 } S_REVERB_PRESET; 253 254 typedef struct 255 { 256 S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets 257 258 } S_REVERB_PRESET_BANK; 259 260 /* parameters for each reverb */ 261 typedef struct 262 { 263 /* controls entire reverb playback volume */ 264 /* to conserve memory, use the MSB and ignore the LSB */ 265 EAS_U8 m_nMasterVolume; 266 267 /* update counter keeps track of when synth params need updating */ 268 /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ 269 EAS_I16 m_nUpdateCounter; 270 271 EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */ 272 273 EAS_U8 m_nFlags; /* misc flags/bit fields */ 274 275 EAS_PCM *m_pOutputBuffer; 276 EAS_PCM *m_pInputBuffer; 277 278 EAS_U16 m_nNumSamplesInOutputBuffer; 279 EAS_U16 m_nNumSamplesInInputBuffer; 280 281 EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer 282 // then get a new input buffer 283 EAS_PCM *m_pNextInputSample; 284 285 EAS_U16 m_nBaseIndex; // base index for circular buffer 286 287 // reverb delay line offsets, allpass parameters, etc: 288 289 EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in 290 291 S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel) 292 293 EAS_U16 m_zD0In; // delay offset for delay line D0 in 294 295 EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in 296 297 S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel) 298 299 EAS_U16 m_zD1In; // delay offset for delay line D1 in 300 301 // delay output taps, notice criss cross order 302 EAS_U16 m_zD0Self; // self feeds forward d0 --> d0 303 304 EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0 305 306 EAS_PCM m_zLpf0; // actual state variable, not a length 307 308 EAS_U16 m_zD1Self; // self feeds forward d1 --> d1 309 310 EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1 311 312 EAS_PCM m_zLpf1; // actual state variable, not a length 313 314 EAS_I16 m_nSin; // gain for self taps 315 316 EAS_I16 m_nCos; // gain for cross taps 317 318 EAS_I16 m_nSinIncrement; // increment for gain 319 320 EAS_I16 m_nCosIncrement; // increment for gain 321 322 EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer) 323 324 EAS_I16 m_nLpfFbk; // lpf feedback gain 325 326 EAS_U16 m_nXfadeInterval; // update/xfade after this many samples 327 328 EAS_U16 m_nXfadeCounter; // keep track of when to xfade 329 330 EAS_I16 m_nPhase; // -1 <= m_nPhase < 1 331 // but during sin,cos calculations 332 // use m_nPhase/2 333 334 EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame 335 336 EAS_I16 m_nNoise; // random noise sample 337 338 EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount 339 340 EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal 341 342 EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output 343 344 EAS_I16 m_nCurrentRoom; // preset number for current room 345 346 EAS_I16 m_nNextRoom; // preset number for next room 347 348 EAS_I16 m_nWet; // gain for wet (processed) signal 349 350 EAS_I16 m_nDry; // gain for dry (unprocessed) signal 351 352 EAS_I16 m_nEarly; // gain for early (widen) signal 353 354 S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections 355 S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections 356 357 EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements 358 359 S_REVERB_PRESET pPreset; 360 361 S_REVERB_PRESET_BANK m_sPreset; 362 363 //EAS_I8 preset; 364 365 } S_REVERB_OBJECT; 366 367 368 /*------------------------------------ 369 * prototypes 370 *------------------------------------ 371 */ 372 373 /*---------------------------------------------------------------------------- 374 * ReverbUpdateXfade 375 *---------------------------------------------------------------------------- 376 * Purpose: 377 * Update the xfade parameters as required 378 * 379 * Inputs: 380 * nNumSamplesToAdd - number of samples to write to buffer 381 * 382 * Outputs: 383 * 384 * 385 * Side Effects: 386 * - xfade parameters will be changed 387 * 388 *---------------------------------------------------------------------------- 389 */ 390 static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd); 391 392 /*---------------------------------------------------------------------------- 393 * ReverbCalculateNoise 394 *---------------------------------------------------------------------------- 395 * Purpose: 396 * Calculate a noise sample and limit its value 397 * 398 * Inputs: 399 * nMaxExcursion - noise value is limited to this value 400 * pnNoise - return new noise sample in this (not limited) 401 * 402 * Outputs: 403 * new limited noise value 404 * 405 * Side Effects: 406 * - *pnNoise noise value is updated 407 * 408 *---------------------------------------------------------------------------- 409 */ 410 static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise); 411 412 /*---------------------------------------------------------------------------- 413 * ReverbCalculateSinCos 414 *---------------------------------------------------------------------------- 415 * Purpose: 416 * Calculate a new sin and cosine value based on the given phase 417 * 418 * Inputs: 419 * nPhase - phase angle 420 * pnSin - input old value, output new value 421 * pnCos - input old value, output new value 422 * 423 * Outputs: 424 * 425 * Side Effects: 426 * - *pnSin, *pnCos are updated 427 * 428 *---------------------------------------------------------------------------- 429 */ 430 static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos); 431 432 /*---------------------------------------------------------------------------- 433 * Reverb 434 *---------------------------------------------------------------------------- 435 * Purpose: 436 * apply reverb to the given signal 437 * 438 * Inputs: 439 * nNu 440 * pnSin - input old value, output new value 441 * pnCos - input old value, output new value 442 * 443 * Outputs: 444 * number of samples actually reverberated 445 * 446 * Side Effects: 447 * 448 *---------------------------------------------------------------------------- 449 */ 450 static EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer); 451 452 /*---------------------------------------------------------------------------- 453 * ReverbReadInPresets() 454 *---------------------------------------------------------------------------- 455 * Purpose: sets global reverb preset bank to defaults 456 * 457 * Inputs: 458 * 459 * Outputs: 460 * 461 *---------------------------------------------------------------------------- 462 */ 463 static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData); 464 465 466 /*---------------------------------------------------------------------------- 467 * ReverbUpdateRoom 468 *---------------------------------------------------------------------------- 469 * Purpose: 470 * Update the room's preset parameters as required 471 * 472 * Inputs: 473 * 474 * Outputs: 475 * 476 * 477 * Side Effects: 478 * - reverb paramters (fbk, fwd, etc) will be changed 479 * - m_nCurrentRoom := m_nNextRoom 480 *---------------------------------------------------------------------------- 481 */ 482 static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); 483 484 #endif /* #ifndef _EAS_REVERBDATA_H */ 485 486 487