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