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