File: Reverb.h

package info (click to toggle)
libopenmpt 0.4.3-1%2Bdeb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,724 kB
  • sloc: cpp: 99,820; sh: 4,503; ansic: 3,449; makefile: 480
file content (283 lines) | stat: -rw-r--r-- 9,990 bytes parent folder | download | duplicates (2)
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
/*
 * Reverb.h
 * --------
 * Purpose: Mixing code for reverb.
 * Notes  : Ugh... This should really be removed at some point.
 * Authors: Olivier Lapicque
 *          OpenMPT Devs
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */

#pragma once

#include "BuildSettings.h"

#ifndef NO_REVERB

#include "../soundlib/Mixer.h"	// For MIXBUFFERSIZE

OPENMPT_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////
// Reverberation

#define NUM_REVERBTYPES			29

mpt::ustring GetReverbPresetName(uint32 nPreset);

/////////////////////////////////////////////////////////////////////////////
//
// SW Reverb structures
//

// Length-1 (in samples) of the reflections delay buffer: 32K, 371ms@22kHz
#define SNDMIX_REFLECTIONS_DELAY_MASK	0x1fff
#define SNDMIX_PREDIFFUSION_DELAY_MASK	0x7f	// 128 samples
#define SNDMIX_REVERB_DELAY_MASK		0xfff	// 4K samples (92ms @ 44kHz)

union LR16
{
	struct { int16 l, r; } c;
	int32 lr;
};

struct SWRvbReflection
{
	uint32 Delay, DelayDest;
	LR16   Gains[2];	// g_ll, g_rl, g_lr, g_rr
};

struct SWRvbRefDelay
{
	uint32 nDelayPos, nPreDifPos, nRefOutPos;
	int32  lMasterGain;			// reflections linear master gain
	LR16   nCoeffs;				// room low-pass coefficients
	LR16   History;				// room low-pass history
	LR16   nPreDifCoeffs;		// prediffusion coefficients
	LR16   ReflectionsGain;		// master reflections gain
	SWRvbReflection Reflections[8];	// Up to 8 SW Reflections
	LR16   RefDelayBuffer[SNDMIX_REFLECTIONS_DELAY_MASK + 1]; // reflections delay buffer
	LR16   PreDifBuffer[SNDMIX_PREDIFFUSION_DELAY_MASK + 1]; // pre-diffusion
	LR16   RefOut[SNDMIX_REVERB_DELAY_MASK + 1]; // stereo output of reflections
};

struct SNDMIX_REVERB_PROPERTIES;


// Late reverberation
// Tank diffusers lengths
#define RVBDIF1L_LEN		(149*2)	// 6.8ms
#define RVBDIF1R_LEN		(223*2)	// 10.1ms
#define RVBDIF2L_LEN		(421*2)	// 19.1ms
#define RVBDIF2R_LEN		(647*2)	// 29.3ms
// Tank delay lines lengths
#define RVBDLY1L_LEN		(683*2)	// 30.9ms
#define RVBDLY1R_LEN	    (811*2) // 36.7ms
#define RVBDLY2L_LEN		(773*2)	// 35.1ms
#define RVBDLY2R_LEN	    (1013*2) // 45.9ms
// Tank delay lines mask
#define RVBDLY_MASK			2047

// Min/Max reflections delay
#define RVBMINREFDELAY		96		// 96 samples
#define RVBMAXREFDELAY		7500	// 7500 samples
// Min/Max reverb delay
#define RVBMINRVBDELAY		128		// 256 samples (11.6ms @ 22kHz)
#define RVBMAXRVBDELAY		3800	// 1900 samples (86ms @ 24kHz)

struct SWLateReverb
{
	uint32 nReverbDelay;		// Reverb delay (in samples)
	uint32 nDelayPos;			// Delay line position
	LR16   nDifCoeffs[2];		// Reverb diffusion
	LR16   nDecayDC[2];			// Reverb DC decay
	LR16   nDecayLP[2];			// Reverb HF decay
	LR16   LPHistory[2];		// Low-pass history
	LR16   Dif2InGains[2];		// 2nd diffuser input gains
	LR16   RvbOutGains[2];		// 4x2 Reverb output gains
	int32  lMasterGain;			// late reverb master gain
	int32  lDummyAlign;
	// Tank Delay lines
	LR16   Diffusion1[RVBDLY_MASK + 1];	// {dif1_l, dif1_r}
	LR16   Diffusion2[RVBDLY_MASK + 1];	// {dif2_l, dif2_r}
	LR16   Delay1[RVBDLY_MASK + 1];		// {dly1_l, dly1_r}
	LR16   Delay2[RVBDLY_MASK + 1];		// {dly2_l, dly2_r}
};

#define ENVIRONMENT_NUMREFLECTIONS		8

struct EnvironmentReflection
{
	int16  GainLL, GainRR, GainLR, GainRL;	// +/- 32K scale
	uint32 Delay;							// In samples
};

struct EnvironmentReverb
{
	int32  ReverbLevel;			// Late reverb gain (mB)
	int32  ReflectionsLevel;	// Master reflections gain (mB)
	int32  RoomHF;				// Room gain HF (mB)
	uint32 ReverbDecay;			// Reverb tank decay (0-7fff scale)
	int32  PreDiffusion;		// Reverb pre-diffusion amount (+/- 32K scale)
	int32  TankDiffusion;		// Reverb tank diffusion (+/- 32K scale)
	uint32 ReverbDelay;			// Reverb delay (in samples)
	float  flReverbDamping;		// HF tank gain [0.0, 1.0]
	int32  ReverbDecaySamples;	// Reverb decay time (in samples)
	EnvironmentReflection Reflections[ENVIRONMENT_NUMREFLECTIONS];
};


class CReverbSettings
{
public:
	uint32 m_nReverbDepth = 8; // 50%
	uint32 m_nReverbType = 0;
};


class CReverb
{
public:
	CReverbSettings m_Settings;

	// Shared reverb state
private:
	mixsample_t MixReverbBuffer[MIXBUFFERSIZE * 2];
public:
	mixsample_t gnRvbROfsVol = 0, gnRvbLOfsVol = 0;

private:
	const SNDMIX_REVERB_PROPERTIES *m_currentPreset = nullptr;

	uint32 gnReverbSend = 0;

	uint32 gnReverbSamples = 0;
	uint32 gnReverbDecaySamples = 0;

	// Internal reverb state
	bool g_bLastInPresent = 0;
	bool g_bLastOutPresent = 0;
	int g_nLastRvbIn_xl = 0;
	int g_nLastRvbIn_xr = 0;
	int g_nLastRvbIn_yl = 0;
	int g_nLastRvbIn_yr = 0;
	int g_nLastRvbOut_xl = 0;
	int g_nLastRvbOut_xr = 0;
	int32 gnDCRRvb_Y1[2] = { 0, 0 };
	int32 gnDCRRvb_X1[2] = { 0, 0 };

	// Reverb mix buffers
	SWRvbRefDelay g_RefDelay;
	SWLateReverb g_LateReverb;

public:
	CReverb();
public:
	void Initialize(bool bReset, uint32 MixingFreq);

	// can be called multiple times or never (if no data is sent to reverb)
	mixsample_t *GetReverbSendBuffer(uint32 nSamples);

	// call once after all data has been sent.
	void Process(mixsample_t *MixSoundBuffer, uint32 nSamples);

private:
	void Shutdown();
	// Pre/Post resampling and filtering
	uint32 ReverbProcessPreFiltering1x(int32 *pWet, uint32 nSamples);
	uint32 ReverbProcessPreFiltering2x(int32 *pWet, uint32 nSamples);
	void ReverbProcessPostFiltering1x(const int32 *pRvb, int32 *pDry, uint32 nSamples);
	void ReverbProcessPostFiltering2x(const int32 *pRvb, int32 *pDry, uint32 nSamples);
	void ReverbDCRemoval(int32 *pBuffer, uint32 nSamples);
	void ReverbDryMix(int32 *pDry, int32 *pWet, int lDryVol, uint32 nSamples);
	// Process pre-diffusion and pre-delay
	static void ProcessPreDelay(SWRvbRefDelay *pPreDelay, const int32 *pIn, uint32 nSamples);
	// Process reflections
	static void ProcessReflections(SWRvbRefDelay *pPreDelay, LR16 *pRefOut, int32 *pMixOut, uint32 nSamples);
	// Process Late Reverb (SW Reflections): stereo reflections output, 32-bit reverb output, SW reverb gain
	static void ProcessLateReverb(SWLateReverb *pReverb, LR16 *pRefOut, int32 *pMixOut, uint32 nSamples);
};


/////////////////////////////////////////////////////////////////////////////////
//
// I3DL2 reverb presets
//

#define SNDMIX_REVERB_PRESET_DEFAULT \
-10000,    0, 1.00f,0.50f,-10000,0.020f,-10000,0.040f,100.0f,100.0f

#define SNDMIX_REVERB_PRESET_GENERIC \
 -1000, -100, 1.49f,0.83f, -2602,0.007f,   200,0.011f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_PADDEDCELL \
 -1000,-6000, 0.17f,0.10f, -1204,0.001f,   207,0.002f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_ROOM \
 -1000, -454, 0.40f,0.83f, -1646,0.002f,    53,0.003f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_BATHROOM \
 -1000,-1200, 1.49f,0.54f,  -370,0.007f,  1030,0.011f,100.0f, 60.0f
#define SNDMIX_REVERB_PRESET_LIVINGROOM \
 -1000,-6000, 0.50f,0.10f, -1376,0.003f, -1104,0.004f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_STONEROOM \
 -1000, -300, 2.31f,0.64f,  -711,0.012f,    83,0.017f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_AUDITORIUM \
 -1000, -476, 4.32f,0.59f,  -789,0.020f,  -289,0.030f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_CONCERTHALL \
 -1000, -500, 3.92f,0.70f, -1230,0.020f,    -2,0.029f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_CAVE \
 -1000,    0, 2.91f,1.30f,  -602,0.015f,  -302,0.022f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_ARENA \
 -1000, -698, 7.24f,0.33f, -1166,0.020f,    16,0.030f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_HANGAR \
 -1000,-1000,10.05f,0.23f,  -602,0.020f,   198,0.030f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_CARPETEDHALLWAY \
 -1000,-4000, 0.30f,0.10f, -1831,0.002f, -1630,0.030f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_HALLWAY \
 -1000, -300, 1.49f,0.59f, -1219,0.007f,   441,0.011f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_STONECORRIDOR \
 -1000, -237, 2.70f,0.79f, -1214,0.013f,   395,0.020f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_ALLEY \
 -1000, -270, 1.49f,0.86f, -1204,0.007f,    -4,0.011f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_FOREST \
 -1000,-3300, 1.49f,0.54f, -2560,0.162f,  -613,0.088f, 79.0f,100.0f
#define SNDMIX_REVERB_PRESET_CITY \
 -1000, -800, 1.49f,0.67f, -2273,0.007f, -2217,0.011f, 50.0f,100.0f
#define SNDMIX_REVERB_PRESET_MOUNTAINS \
 -1000,-2500, 1.49f,0.21f, -2780,0.300f, -2014,0.100f, 27.0f,100.0f
#define SNDMIX_REVERB_PRESET_QUARRY \
 -1000,-1000, 1.49f,0.83f,-10000,0.061f,   500,0.025f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_PLAIN \
 -1000,-2000, 1.49f,0.50f, -2466,0.179f, -2514,0.100f, 21.0f,100.0f
#define SNDMIX_REVERB_PRESET_PARKINGLOT \
 -1000,    0, 1.65f,1.50f, -1363,0.008f, -1153,0.012f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_SEWERPIPE \
 -1000,-1000, 2.81f,0.14f,   429,0.014f,   648,0.021f, 80.0f, 60.0f
#define SNDMIX_REVERB_PRESET_UNDERWATER \
 -1000,-4000, 1.49f,0.10f,  -449,0.007f,  1700,0.011f,100.0f,100.0f

// Examples simulating General MIDI 2'musical' reverb presets
//
// Name  (Decay time)  Description
//
// Small Room  (1.1s)  A small size room with a length of 5m or so.
// Medium Room (1.3s)  A medium size room with a length of 10m or so.
// Large Room  (1.5s)  A large size room suitable for live performances.
// Medium Hall (1.8s)  A medium size concert hall.
// Large Hall  (1.8s)  A large size concert hall suitable for a full orchestra.
// Plate       (1.3s)  A plate reverb simulation.

#define SNDMIX_REVERB_PRESET_SMALLROOM \
 -1000, -600, 1.10f,0.83f,  -400,0.005f,   500,0.010f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_MEDIUMROOM \
 -1000, -600, 1.30f,0.83f, -1000,0.010f,  -200,0.020f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_LARGEROOM \
 -1000, -600, 1.50f,0.83f, -1600,0.020f, -1000,0.040f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_MEDIUMHALL \
 -1000, -600, 1.80f,0.70f, -1300,0.015f,  -800,0.030f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_LARGEHALL \
 -1000, -600, 1.80f,0.70f, -2000,0.030f, -1400,0.060f,100.0f,100.0f
#define SNDMIX_REVERB_PRESET_PLATE \
 -1000, -200, 1.30f,0.90f,     0,0.002f,     0,0.010f,100.0f, 75.0f

OPENMPT_NAMESPACE_END

#endif // NO_REVERB