eas_reverbdata.h revision a8c89077d78769bf4840fa91609edc51fe2fa02d
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