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