summaryrefslogtreecommitdiffstats
path: root/media/libeffects/EffectReverb.h
blob: 578e09e64266d65022e7afd2c894e7cb203cec03 (plain)
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
/*
 * 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/EffectReverbApi.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_MAX_ROOM_TYPE            4   // any room numbers larger than this are invalid
#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)


/* 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_MAX_ROOM_TYPE];    //array of presets

} 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

} 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 EffectQueryNext(effect_descriptor_t *pDescriptor);
int EffectCreate(effect_uuid_t *effectUID, 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, int cmdCode, int cmdSize, void *pCmdData, int *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_*/