Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef ANDROID_EFFECTREVERB_H_ |
| 18 | #define ANDROID_EFFECTREVERB_H_ |
| 19 | |
Eric Laurent | 5cc0526 | 2011-06-24 07:01:31 -0700 | [diff] [blame] | 20 | #include <audio_effects/effect_environmentalreverb.h> |
| 21 | #include <audio_effects/effect_presetreverb.h> |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 22 | |
| 23 | |
| 24 | /*------------------------------------ |
| 25 | * defines |
| 26 | *------------------------------------ |
| 27 | */ |
| 28 | |
| 29 | /* |
| 30 | CIRCULAR() calculates the array index using modulo arithmetic. |
| 31 | The "trick" is that modulo arithmetic is simplified by masking |
| 32 | the effective address where the mask is (2^n)-1. This only works |
| 33 | if the buffer size is a power of two. |
| 34 | */ |
| 35 | #define CIRCULAR(base,offset,size) (uint32_t)( \ |
| 36 | ( \ |
| 37 | ((int32_t)(base)) + ((int32_t)(offset)) \ |
| 38 | ) \ |
| 39 | & size \ |
| 40 | ) |
| 41 | |
| 42 | #define NUM_OUTPUT_CHANNELS 2 |
Eric Laurent | 0fb66c2 | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 43 | #define OUTPUT_CHANNELS AUDIO_CHANNEL_OUT_STEREO |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 44 | |
| 45 | #define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX 16384 |
| 46 | |
Eric Laurent | fd84f97 | 2010-07-08 15:32:51 -0700 | [diff] [blame] | 47 | #define REVERB_NUM_PRESETS REVERB_PRESET_PLATE // REVERB_PRESET_NONE is not included |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 48 | #define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel |
| 49 | |
| 50 | |
| 51 | // xfade parameters |
| 52 | #define REVERB_XFADE_PERIOD_IN_SECONDS (double) (100.0 / 1000.0) // xfade once every this many seconds |
| 53 | |
| 54 | |
| 55 | /**********/ |
| 56 | /* the entire synth uses various flags in a bit field */ |
| 57 | |
| 58 | /* if flag is set, synth reset has been requested */ |
| 59 | #define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ |
| 60 | #define MASK_REVERB_RESET_IS_REQUESTED 0x01 |
| 61 | #define MASK_REVERB_RESET_IS_NOT_REQUESTED (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED) |
| 62 | |
| 63 | /* |
| 64 | by default, we always want to update ALL channel parameters |
| 65 | when we reset the synth (e.g., during GM ON) |
| 66 | */ |
| 67 | #define DEFAULT_REVERB_FLAGS 0x0 |
| 68 | |
| 69 | /* coefficients for generating sin, cos */ |
| 70 | #define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ |
| 71 | /* |
| 72 | int32_t nPanG1 = +1.0 for sin |
| 73 | int32_t nPanG1 = -1.0 for cos |
| 74 | */ |
| 75 | #define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ |
| 76 | |
| 77 | /*************************************************************/ |
| 78 | // define the input injection points |
| 79 | #define GUARD 5 // safety guard of this many samples |
| 80 | |
| 81 | #define MAX_AP_TIME (int) ((20*65536)/1000) // delay time in time units (65536th of sec) |
| 82 | #define MAX_DELAY_TIME (int) ((65*65536)/1000) // delay time in time units |
| 83 | #define MAX_EARLY_TIME (int) ((65*65536)/1000) // delay time in time units |
| 84 | |
| 85 | #define AP0_IN 0 |
| 86 | |
| 87 | |
| 88 | #define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number |
| 89 | #define DEFAULT_AP0_GAIN 19400 |
| 90 | #define DEFAULT_AP1_GAIN -19400 |
| 91 | |
| 92 | #define REVERB_DEFAULT_WET 32767 |
| 93 | #define REVERB_DEFAULT_DRY 0 |
| 94 | |
| 95 | #define REVERB_WET_MAX 32767 |
| 96 | #define REVERB_WET_MIN 0 |
| 97 | #define REVERB_DRY_MAX 32767 |
| 98 | #define REVERB_DRY_MIN 0 |
| 99 | |
| 100 | // constants for reverb density |
| 101 | // The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by |
| 102 | // AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE |
| 103 | #define AP0_TIME_BASE (int)((9*65536)/1000) |
| 104 | #define AP0_TIME_RANGE (int)((4*65536)/1000) |
| 105 | #define AP1_TIME_BASE (int)((12*65536)/1000) |
| 106 | #define AP1_TIME_RANGE (int)((8*65536)/1000) |
| 107 | |
| 108 | // constants for reverb diffusion |
| 109 | // The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by |
| 110 | // AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE |
| 111 | #define AP0_GAIN_BASE (int)(9830) |
| 112 | #define AP0_GAIN_RANGE (int)(19660-9830) |
| 113 | #define AP1_GAIN_BASE (int)(6553) |
| 114 | #define AP1_GAIN_RANGE (int)(22936-6553) |
| 115 | |
| 116 | |
Eric Laurent | 7d850f2 | 2010-07-09 13:34:17 -0700 | [diff] [blame] | 117 | enum reverb_state_e { |
| 118 | REVERB_STATE_UNINITIALIZED, |
| 119 | REVERB_STATE_INITIALIZED, |
| 120 | REVERB_STATE_ACTIVE, |
| 121 | }; |
| 122 | |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 123 | /* parameters for each allpass */ |
| 124 | typedef struct |
| 125 | { |
| 126 | uint16_t m_zApOut; // delay offset for ap out |
| 127 | |
| 128 | int16_t m_nApGain; // gain for ap |
| 129 | |
| 130 | uint16_t m_zApIn; // delay offset for ap in |
| 131 | |
| 132 | } allpass_object_t; |
| 133 | |
| 134 | |
| 135 | /* parameters for early reflections */ |
| 136 | typedef struct |
| 137 | { |
| 138 | uint16_t m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out |
| 139 | |
| 140 | int16_t m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap |
| 141 | |
| 142 | } early_reflection_object_t; |
| 143 | |
| 144 | //demo |
| 145 | typedef struct |
| 146 | { |
| 147 | int16_t m_nRvbLpfFbk; |
| 148 | int16_t m_nRvbLpfFwd; |
| 149 | int16_t m_nRoomLpfFbk; |
| 150 | int16_t m_nRoomLpfFwd; |
| 151 | |
| 152 | int16_t m_nEarlyGain; |
| 153 | int16_t m_nEarlyDelay; |
| 154 | int16_t m_nLateGain; |
| 155 | int16_t m_nLateDelay; |
| 156 | |
| 157 | early_reflection_object_t m_sEarlyL; |
| 158 | early_reflection_object_t m_sEarlyR; |
| 159 | |
| 160 | uint16_t m_nMaxExcursion; //28 |
| 161 | int16_t m_nXfadeInterval; |
| 162 | |
| 163 | int16_t m_nAp0_ApGain; //30 |
| 164 | int16_t m_nAp0_ApOut; |
| 165 | int16_t m_nAp1_ApGain; |
| 166 | int16_t m_nAp1_ApOut; |
| 167 | int16_t m_nDiffusion; |
| 168 | |
| 169 | int16_t m_rfu4; |
| 170 | int16_t m_rfu5; |
| 171 | int16_t m_rfu6; |
| 172 | int16_t m_rfu7; |
| 173 | int16_t m_rfu8; |
| 174 | int16_t m_rfu9; |
| 175 | int16_t m_rfu10; //43 |
| 176 | |
| 177 | } reverb_preset_t; |
| 178 | |
| 179 | typedef struct |
| 180 | { |
Eric Laurent | fd84f97 | 2010-07-08 15:32:51 -0700 | [diff] [blame] | 181 | reverb_preset_t m_sPreset[REVERB_NUM_PRESETS]; // array of presets(does not include REVERB_PRESET_NONE) |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 182 | |
| 183 | } reverb_preset_bank_t; |
| 184 | |
| 185 | |
| 186 | /* parameters for each reverb */ |
| 187 | typedef struct |
| 188 | { |
| 189 | /* update counter keeps track of when synth params need updating */ |
| 190 | /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ |
| 191 | int16_t m_nUpdateCounter; |
| 192 | |
| 193 | uint16_t m_nBaseIndex; // base index for circular buffer |
| 194 | |
| 195 | // reverb delay line offsets, allpass parameters, etc: |
| 196 | |
| 197 | short m_nRevFbkR; // combine feedback reverb right out with dry left in |
| 198 | short m_zOutLpfL; // left reverb output |
| 199 | |
| 200 | allpass_object_t m_sAp0; // allpass 0 (left channel) |
| 201 | |
| 202 | uint16_t m_zD0In; // delay offset for delay line D0 in |
| 203 | |
| 204 | short m_nRevFbkL; // combine feedback reverb left out with dry right in |
| 205 | short m_zOutLpfR; // right reverb output |
| 206 | |
| 207 | allpass_object_t m_sAp1; // allpass 1 (right channel) |
| 208 | |
| 209 | uint16_t m_zD1In; // delay offset for delay line D1 in |
| 210 | |
| 211 | // delay output taps, notice criss cross order |
| 212 | uint16_t m_zD0Self; // self feeds forward d0 --> d0 |
| 213 | |
| 214 | uint16_t m_zD1Cross; // cross feeds across d1 --> d0 |
| 215 | |
| 216 | uint16_t m_zD1Self; // self feeds forward d1 --> d1 |
| 217 | |
| 218 | uint16_t m_zD0Cross; // cross feeds across d0 --> d1 |
| 219 | |
| 220 | int16_t m_nSin; // gain for self taps |
| 221 | |
| 222 | int16_t m_nCos; // gain for cross taps |
| 223 | |
| 224 | int16_t m_nSinIncrement; // increment for gain |
| 225 | |
| 226 | int16_t m_nCosIncrement; // increment for gain |
| 227 | |
| 228 | int16_t m_nRvbLpfFwd; // reverb feedback lpf forward gain (includes scaling for mixer) |
| 229 | |
| 230 | int16_t m_nRvbLpfFbk; // reverb feedback lpf feedback gain |
| 231 | |
| 232 | int16_t m_nRoomLpfFwd; // room lpf forward gain (includes scaling for mixer) |
| 233 | |
| 234 | int16_t m_nRoomLpfFbk; // room lpf feedback gain |
| 235 | |
| 236 | uint16_t m_nXfadeInterval; // update/xfade after this many samples |
| 237 | |
| 238 | uint16_t m_nXfadeCounter; // keep track of when to xfade |
| 239 | |
| 240 | int16_t m_nPhase; // -1 <= m_nPhase < 1 |
| 241 | // but during sin,cos calculations |
| 242 | // use m_nPhase/2 |
| 243 | |
| 244 | int16_t m_nPhaseIncrement; // add this to m_nPhase each frame |
| 245 | |
| 246 | int16_t m_nNoise; // random noise sample |
| 247 | |
| 248 | uint16_t m_nMaxExcursion; // the taps can excurse +/- this amount |
| 249 | |
| 250 | uint16_t m_bUseNoise; // if TRUE, use noise as input signal |
| 251 | |
| 252 | uint16_t m_bBypass; // if TRUE, then bypass reverb and copy input to output |
| 253 | |
| 254 | int16_t m_nCurrentRoom; // preset number for current room |
| 255 | |
| 256 | int16_t m_nNextRoom; // preset number for next room |
| 257 | |
| 258 | int16_t m_nEarlyGain; // gain for early (widen) signal |
| 259 | int16_t m_nEarlyDelay; // initial dealy for early (widen) signal |
| 260 | int16_t m_nEarly0in; |
| 261 | int16_t m_nEarly1in; |
| 262 | int16_t m_nLateGain; // gain for late reverb |
| 263 | int16_t m_nLateDelay; |
| 264 | |
| 265 | int16_t m_nDiffusion; |
| 266 | |
| 267 | early_reflection_object_t m_sEarlyL; // left channel early reflections |
| 268 | early_reflection_object_t m_sEarlyR; // right channel early reflections |
| 269 | |
| 270 | short m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX]; // one large delay line for all reverb elements |
| 271 | |
| 272 | reverb_preset_t pPreset; |
| 273 | |
| 274 | reverb_preset_bank_t m_sPreset; |
| 275 | |
| 276 | //int8_t preset; |
| 277 | uint32_t m_nSamplingRate; |
| 278 | int32_t m_nUpdatePeriodInBits; |
| 279 | int32_t m_nBufferMask; |
| 280 | int32_t m_nUpdatePeriodInSamples; |
| 281 | int32_t m_nDelay0Out; |
| 282 | int32_t m_nDelay1Out; |
| 283 | int16_t m_nCosWT_5KHz; |
| 284 | |
| 285 | uint16_t m_Aux; // if TRUE, is connected as auxiliary effect |
| 286 | uint16_t m_Preset; // if TRUE, expose preset revert interface |
| 287 | |
Eric Laurent | 7d850f2 | 2010-07-09 13:34:17 -0700 | [diff] [blame] | 288 | uint32_t mState; |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 289 | } reverb_object_t; |
| 290 | |
| 291 | |
| 292 | |
| 293 | typedef struct reverb_module_s { |
| 294 | const struct effect_interface_s *itfe; |
| 295 | effect_config_t config; |
| 296 | reverb_object_t context; |
| 297 | } reverb_module_t; |
| 298 | |
| 299 | /*------------------------------------ |
| 300 | * Effect API |
| 301 | *------------------------------------ |
| 302 | */ |
Eric Laurent | 65b6545 | 2010-06-01 23:49:17 -0700 | [diff] [blame] | 303 | int EffectQueryNumberEffects(uint32_t *pNumEffects); |
Eric Laurent | a4c72ac | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 304 | int EffectQueryEffect(uint32_t index, |
| 305 | effect_descriptor_t *pDescriptor); |
| 306 | int EffectCreate(effect_uuid_t *effectUID, |
| 307 | int32_t sessionId, |
| 308 | int32_t ioId, |
Eric Laurent | 0fb66c2 | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 309 | effect_handle_t *pHandle); |
| 310 | int EffectRelease(effect_handle_t handle); |
| 311 | int EffectGetDescriptor(effect_uuid_t *uuid, |
| 312 | effect_descriptor_t *pDescriptor); |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 313 | |
Eric Laurent | 0fb66c2 | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 314 | static int Reverb_Process(effect_handle_t self, |
Eric Laurent | a4c72ac | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 315 | audio_buffer_t *inBuffer, |
| 316 | audio_buffer_t *outBuffer); |
Eric Laurent | 0fb66c2 | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 317 | static int Reverb_Command(effect_handle_t self, |
Eric Laurent | a4c72ac | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 318 | uint32_t cmdCode, |
| 319 | uint32_t cmdSize, |
| 320 | void *pCmdData, |
| 321 | uint32_t *replySize, |
| 322 | void *pReplyData); |
Eric Laurent | 0fb66c2 | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 323 | static int Reverb_GetDescriptor(effect_handle_t self, |
| 324 | effect_descriptor_t *pDescriptor); |
Eric Laurent | 5fe37c6 | 2010-05-21 06:05:13 -0700 | [diff] [blame] | 325 | |
| 326 | /*------------------------------------ |
| 327 | * internal functions |
| 328 | *------------------------------------ |
| 329 | */ |
| 330 | |
| 331 | int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset); |
| 332 | int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init); |
| 333 | void Reverb_Reset(reverb_object_t *pReverb, bool init); |
| 334 | |
| 335 | int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue); |
| 336 | int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue); |
| 337 | |
| 338 | /*---------------------------------------------------------------------------- |
| 339 | * ReverbUpdateXfade |
| 340 | *---------------------------------------------------------------------------- |
| 341 | * Purpose: |
| 342 | * Update the xfade parameters as required |
| 343 | * |
| 344 | * Inputs: |
| 345 | * nNumSamplesToAdd - number of samples to write to buffer |
| 346 | * |
| 347 | * Outputs: |
| 348 | * |
| 349 | * |
| 350 | * Side Effects: |
| 351 | * - xfade parameters will be changed |
| 352 | * |
| 353 | *---------------------------------------------------------------------------- |
| 354 | */ |
| 355 | static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd); |
| 356 | |
| 357 | /*---------------------------------------------------------------------------- |
| 358 | * ReverbCalculateNoise |
| 359 | *---------------------------------------------------------------------------- |
| 360 | * Purpose: |
| 361 | * Calculate a noise sample and limit its value |
| 362 | * |
| 363 | * Inputs: |
| 364 | * Pointer to reverb context |
| 365 | * |
| 366 | * Outputs: |
| 367 | * new limited noise value |
| 368 | * |
| 369 | * Side Effects: |
| 370 | * - pReverbData->m_nNoise value is updated |
| 371 | * |
| 372 | *---------------------------------------------------------------------------- |
| 373 | */ |
| 374 | static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData); |
| 375 | |
| 376 | /*---------------------------------------------------------------------------- |
| 377 | * ReverbCalculateSinCos |
| 378 | *---------------------------------------------------------------------------- |
| 379 | * Purpose: |
| 380 | * Calculate a new sin and cosine value based on the given phase |
| 381 | * |
| 382 | * Inputs: |
| 383 | * nPhase - phase angle |
| 384 | * pnSin - input old value, output new value |
| 385 | * pnCos - input old value, output new value |
| 386 | * |
| 387 | * Outputs: |
| 388 | * |
| 389 | * Side Effects: |
| 390 | * - *pnSin, *pnCos are updated |
| 391 | * |
| 392 | *---------------------------------------------------------------------------- |
| 393 | */ |
| 394 | static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos); |
| 395 | |
| 396 | /*---------------------------------------------------------------------------- |
| 397 | * Reverb |
| 398 | *---------------------------------------------------------------------------- |
| 399 | * Purpose: |
| 400 | * apply reverb to the given signal |
| 401 | * |
| 402 | * Inputs: |
| 403 | * nNu |
| 404 | * pnSin - input old value, output new value |
| 405 | * pnCos - input old value, output new value |
| 406 | * |
| 407 | * Outputs: |
| 408 | * number of samples actually reverberated |
| 409 | * |
| 410 | * Side Effects: |
| 411 | * |
| 412 | *---------------------------------------------------------------------------- |
| 413 | */ |
| 414 | static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer); |
| 415 | |
| 416 | /*---------------------------------------------------------------------------- |
| 417 | * ReverbReadInPresets() |
| 418 | *---------------------------------------------------------------------------- |
| 419 | * Purpose: sets global reverb preset bank to defaults |
| 420 | * |
| 421 | * Inputs: |
| 422 | * |
| 423 | * Outputs: |
| 424 | * |
| 425 | *---------------------------------------------------------------------------- |
| 426 | */ |
| 427 | static int ReverbReadInPresets(reverb_object_t* pReverbData); |
| 428 | |
| 429 | |
| 430 | /*---------------------------------------------------------------------------- |
| 431 | * ReverbUpdateRoom |
| 432 | *---------------------------------------------------------------------------- |
| 433 | * Purpose: |
| 434 | * Update the room's preset parameters as required |
| 435 | * |
| 436 | * Inputs: |
| 437 | * |
| 438 | * Outputs: |
| 439 | * |
| 440 | * |
| 441 | * Side Effects: |
| 442 | * - reverb paramters (fbk, fwd, etc) will be changed |
| 443 | * - m_nCurrentRoom := m_nNextRoom |
| 444 | *---------------------------------------------------------------------------- |
| 445 | */ |
| 446 | static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate); |
| 447 | |
| 448 | |
| 449 | static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate); |
| 450 | |
| 451 | #endif /*ANDROID_EFFECTREVERB_H_*/ |