summaryrefslogtreecommitdiffstats
path: root/arm-wt-22k/lib_src/eas_reverbdata.h
blob: ef424da1237ba7614c1db60d0612187f9c7dd8bd (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
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
/*----------------------------------------------------------------------------
 *
 * File: 
 * eas_reverbdata.h
 *
 * Contents and purpose:
 * Contains the prototypes for the Reverb effect.
 *
 *
 * Copyright Sonic Network Inc. 2006

 * 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.
 *
 *----------------------------------------------------------------------------
 * Revision Control:
 *   $Revision: 499 $
 *   $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
 *----------------------------------------------------------------------------
*/

#ifndef _EAS_REVERBDATA_H
#define _EAS_REVERBDATA_H

#include "eas_types.h"
#include "eas_audioconst.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) (EAS_U32)(				\
			(												\
				((EAS_I32)(base)) + ((EAS_I32)(offset))		\
			)												\
			& size											\
											)

/* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */
#if	defined (_SAMPLE_RATE_8000)

#define	REVERB_UPDATE_PERIOD_IN_BITS		5
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		2048

#elif defined (_SAMPLE_RATE_16000)

#define	REVERB_UPDATE_PERIOD_IN_BITS		6
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		4096

#elif defined (_SAMPLE_RATE_22050)

#define	REVERB_UPDATE_PERIOD_IN_BITS		7
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		4096

#elif defined (_SAMPLE_RATE_32000)

#define	REVERB_UPDATE_PERIOD_IN_BITS		7
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		8192

#elif defined (_SAMPLE_RATE_44100)

#define	REVERB_UPDATE_PERIOD_IN_BITS		8
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		8192

#elif defined (_SAMPLE_RATE_48000)

#define	REVERB_UPDATE_PERIOD_IN_BITS		8
#define	REVERB_BUFFER_SIZE_IN_SAMPLES		8192

#endif

// Define a mask for circular addressing, so that array index
// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
// The buffer size MUST be a power of two
#define	REVERB_BUFFER_MASK					(REVERB_BUFFER_SIZE_IN_SAMPLES -1)

#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

/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */
#define REVERB_UPDATE_PERIOD_IN_SAMPLES	(EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS)

/*
calculate the update counter by bitwise ANDING with this value to 
generate a 2^n modulo value
*/
#define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES	(EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1)

/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */
#define REVERB_UPDATE_PERIOD_IN_SECONDS		(REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE)

// xfade parameters
#define	REVERB_XFADE_PERIOD_IN_SECONDS		(100.0 / 1000.0)		// xfade once every this many seconds

#define	REVERB_XFADE_PERIOD_IN_SAMPLES		(REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE)

#define	REVERB_XFADE_PHASE_INCREMENT	(EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES))

/**********/
/* 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		(EAS_U32)(~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) */
/*
EAS_I32 nPanG1 = +1.0 for sin
EAS_I32 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			(double) (20.0/1000.0)	// delay time in milliseconds
#define	MAX_DELAY_TIME		(double) (65.0/1000.0)	// delay time in milliseconds

#define	MAX_AP_SAMPLES		(int)(((double) MAX_AP_TIME)	* ((double) _OUTPUT_SAMPLE_RATE))
#define	MAX_DELAY_SAMPLES	(int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE))

#define	AP0_IN				0
#define	AP1_IN				(AP0_IN		+ MAX_AP_SAMPLES	+ GUARD)
#define	DELAY0_IN			(AP1_IN		+ MAX_AP_SAMPLES	+ GUARD)
#define	DELAY1_IN			(DELAY0_IN	+ MAX_DELAY_SAMPLES	+ GUARD)

// Define the max offsets for the end points of each section
// i.e., we don't expect a given section's taps to go beyond
// the following limits
#define	AP0_OUT				(AP0_IN		+ MAX_AP_SAMPLES	-1)
#define	AP1_OUT				(AP1_IN		+ MAX_AP_SAMPLES	-1)
#define	DELAY0_OUT			(DELAY0_IN	+ MAX_DELAY_SAMPLES	-1)
#define	DELAY1_OUT			(DELAY1_IN	+ MAX_DELAY_SAMPLES	-1)

#define	REVERB_DEFAULT_ROOM_NUMBER		1		// default preset number 
#define	DEFAULT_AP0_LENGTH				(int)(((double) (17.0/1000.0))	* ((double) _OUTPUT_SAMPLE_RATE))
#define	DEFAULT_AP0_GAIN				19400
#define	DEFAULT_AP1_LENGTH				(int)(((double) (16.5/1000.0))	* ((double) _OUTPUT_SAMPLE_RATE))
#define	DEFAULT_AP1_GAIN				-19400

#define	REVERB_DEFAULT_WET				32767
#define	REVERB_DEFAULT_DRY				0

#define EAS_REVERB_WET_MAX				32767
#define EAS_REVERB_WET_MIN				0
#define EAS_REVERB_DRY_MAX				32767
#define EAS_REVERB_DRY_MIN				0

/* parameters for each allpass */
typedef struct
{
	EAS_U16				m_zApOut;		// delay offset for ap out

	EAS_I16				m_nApGain;		// gain for ap

	EAS_U16				m_zApIn;		// delay offset for ap in

} S_ALLPASS_OBJECT;


/* parameters for each allpass */
typedef struct
{
	EAS_PCM				m_zLpf;						// actual state variable, not a length

	EAS_I16				m_nLpfFwd;					// lpf forward gain

	EAS_I16				m_nLpfFbk;					// lpf feedback gain

	EAS_U16				m_zDelay[REVERB_MAX_NUM_REFLECTIONS];	// delay offset for ap out

	EAS_I16				m_nGain[REVERB_MAX_NUM_REFLECTIONS];	// gain for ap

} S_EARLY_REFLECTION_OBJECT;

//demo
typedef struct
{
	EAS_I16				m_nLpfFbk;
	EAS_I16				m_nLpfFwd;

	EAS_I16				m_nEarly;
	EAS_I16				m_nWet;
	EAS_I16				m_nDry;

	EAS_I16				m_nEarlyL_LpfFbk;
	EAS_I16				m_nEarlyL_LpfFwd;

	EAS_I16				m_nEarlyL_Delay0; //8
	EAS_I16				m_nEarlyL_Gain0;
	EAS_I16				m_nEarlyL_Delay1;
	EAS_I16				m_nEarlyL_Gain1;
	EAS_I16				m_nEarlyL_Delay2;
	EAS_I16				m_nEarlyL_Gain2;
	EAS_I16				m_nEarlyL_Delay3;
	EAS_I16				m_nEarlyL_Gain3;
	EAS_I16				m_nEarlyL_Delay4;
	EAS_I16				m_nEarlyL_Gain4;

	EAS_I16				m_nEarlyR_Delay0; //18
	EAS_I16				m_nEarlyR_Gain0;
	EAS_I16				m_nEarlyR_Delay1;
	EAS_I16				m_nEarlyR_Gain1;
	EAS_I16				m_nEarlyR_Delay2;
	EAS_I16				m_nEarlyR_Gain2;
	EAS_I16				m_nEarlyR_Delay3;
	EAS_I16				m_nEarlyR_Gain3;
	EAS_I16				m_nEarlyR_Delay4;
	EAS_I16				m_nEarlyR_Gain4;

	EAS_U16				m_nMaxExcursion; //28
	EAS_I16				m_nXfadeInterval;

	EAS_I16				m_nAp0_ApGain; //30
	EAS_I16				m_nAp0_ApOut;
	EAS_I16				m_nAp1_ApGain;
	EAS_I16				m_nAp1_ApOut;

	EAS_I16				m_rfu4;
	EAS_I16				m_rfu5;
	EAS_I16				m_rfu6;
	EAS_I16				m_rfu7;
	EAS_I16				m_rfu8;
	EAS_I16				m_rfu9;
	EAS_I16				m_rfu10; //43

} S_REVERB_PRESET;

typedef struct
{
	S_REVERB_PRESET		m_sPreset[REVERB_MAX_ROOM_TYPE];	//array of presets

} S_REVERB_PRESET_BANK;

/* parameters for each reverb */
typedef struct
{
	/* controls entire reverb playback volume */
	/* to conserve memory, use the MSB and ignore the LSB */
	EAS_U8				m_nMasterVolume;

	/* update counter keeps track of when synth params need updating */
	/* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
	EAS_I16				m_nUpdateCounter;	
	
	EAS_U16				m_nMinSamplesToAdd;			/* ComputeReverb() generates this many samples */

	EAS_U8				m_nFlags;					/* misc flags/bit fields */
	
	EAS_PCM				*m_pOutputBuffer;
	EAS_PCM				*m_pInputBuffer;

	EAS_U16				m_nNumSamplesInOutputBuffer;
	EAS_U16				m_nNumSamplesInInputBuffer;

	EAS_U16				m_nNumInputSamplesRead;		// if m_nNumInputSamplesRead >= NumSamplesInInputBuffer 
													// then get a new input buffer
	EAS_PCM				*m_pNextInputSample;

	EAS_U16				m_nBaseIndex;									// base index for circular buffer

	// reverb delay line offsets, allpass parameters, etc:

	EAS_PCM				m_nRevOutFbkR;				// combine feedback reverb right out with dry left in

	S_ALLPASS_OBJECT	m_sAp0;						// allpass 0 (left channel)

	EAS_U16				m_zD0In;					// delay offset for delay line D0 in

	EAS_PCM				m_nRevOutFbkL;				// combine feedback reverb left out with dry right in

	S_ALLPASS_OBJECT	m_sAp1;						// allpass 1 (right channel)

	EAS_U16				m_zD1In;					// delay offset for delay line D1 in

	// delay output taps, notice criss cross order
	EAS_U16				m_zD0Self;					// self feeds forward d0 --> d0

	EAS_U16				m_zD1Cross;					// cross feeds across d1 --> d0

	EAS_PCM				m_zLpf0;					// actual state variable, not a length

	EAS_U16				m_zD1Self;					// self feeds forward d1 --> d1

	EAS_U16				m_zD0Cross;					// cross feeds across d0 --> d1

	EAS_PCM				m_zLpf1;					// actual state variable, not a length

	EAS_I16				m_nSin;						// gain for self taps

	EAS_I16				m_nCos;						// gain for cross taps

	EAS_I16				m_nSinIncrement;			// increment for gain

	EAS_I16				m_nCosIncrement;			// increment for gain

	EAS_I16				m_nLpfFwd;					// lpf forward gain (includes scaling for mixer)

	EAS_I16				m_nLpfFbk;					// lpf feedback gain

	EAS_U16				m_nXfadeInterval;			// update/xfade after this many samples

	EAS_U16				m_nXfadeCounter;			// keep track of when to xfade

	EAS_I16				m_nPhase;					// -1 <= m_nPhase < 1
													// but during sin,cos calculations
													// use m_nPhase/2

	EAS_I16				m_nPhaseIncrement;			// add this to m_nPhase each frame

	EAS_I16				m_nNoise;					// random noise sample

	EAS_U16				m_nMaxExcursion;			// the taps can excurse +/- this amount

	EAS_BOOL			m_bUseNoise;				// if EAS_TRUE, use noise as input signal

	EAS_BOOL			m_bBypass;					// if EAS_TRUE, then bypass reverb and copy input to output

	EAS_I16				m_nCurrentRoom;				// preset number for current room

	EAS_I16				m_nNextRoom;				// preset number for next room

	EAS_I16				m_nWet;						// gain for wet (processed) signal

	EAS_I16				m_nDry;						// gain for dry (unprocessed) signal

	EAS_I16				m_nEarly;					// gain for early (widen) signal
	
	S_EARLY_REFLECTION_OBJECT	m_sEarlyL;			// left channel early reflections
	S_EARLY_REFLECTION_OBJECT	m_sEarlyR;			// right channel early reflections

	EAS_PCM				m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES];	// one large delay line for all reverb elements

	S_REVERB_PRESET		pPreset;

	S_REVERB_PRESET_BANK	m_sPreset;

	//EAS_I8			preset;

} S_REVERB_OBJECT;


/*------------------------------------
 * prototypes
 *------------------------------------
*/

/*----------------------------------------------------------------------------
 * 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 EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd);

/*----------------------------------------------------------------------------
 * ReverbCalculateNoise
 *----------------------------------------------------------------------------
 * Purpose: 
 * Calculate a noise sample and limit its value
 *
 * Inputs: 
 * nMaxExcursion - noise value is limited to this value
 * pnNoise - return new noise sample in this (not limited)
 *
 * Outputs:
 * new limited noise value
 * 
 * Side Effects:
 * - *pnNoise noise value is updated
 *
 *----------------------------------------------------------------------------
*/
static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise);

/*----------------------------------------------------------------------------
 * 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 EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *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 EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer);

/*----------------------------------------------------------------------------
 * ReverbReadInPresets()
 *----------------------------------------------------------------------------
 * Purpose: sets global reverb preset bank to defaults
 * 
 * Inputs: 
 *			
 * Outputs:
 *
 *----------------------------------------------------------------------------
*/
static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* 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 EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData);

#endif /* #ifndef _EAS_REVERBDATA_H */