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/* 43CIRCULAR() calculates the array index using modulo arithmetic. 44The "trick" is that modulo arithmetic is simplified by masking 45the effective address where the mask is (2^n)-1. This only works 46if 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/* 100calculate the update counter by bitwise ANDING with this value to 101generate 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/* 124by default, we always want to update ALL channel parameters 125when 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/* 132EAS_I32 nPanG1 = +1.0 for sin 133EAS_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 */ 175typedef 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 */ 187typedef 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 202typedef 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 254typedef 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 */ 261typedef 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*/ 390static 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*/ 410static 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*/ 430static 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*/ 450static 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*/ 463static 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*/ 482static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); 483 484#endif /* #ifndef _EAS_REVERBDATA_H */ 485 486 487