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
|
/*
* 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 "openmpt/all/BuildSettings.hpp"
#ifndef NO_REVERB
#include "../soundlib/Mixer.h" // For MIXBUFFERSIZE
OPENMPT_NAMESPACE_BEGIN
////////////////////////////////////////////////////////////////////////
// Reverberation
/////////////////////////////////////////////////////////////////////////////
//
// 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;
private:
const SNDMIX_REVERB_PROPERTIES *m_currentPreset = nullptr;
bool gnReverbSend = false;
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, MixSampleInt &gnRvbROfsVol, MixSampleInt &gnRvbLOfsVol, uint32 MixingFreq);
// can be called multiple times or never (if no data is sent to reverb)
void TouchReverbSendBuffer(MixSampleInt *MixReverbBuffer, MixSampleInt &gnRvbROfsVol, MixSampleInt &gnRvbLOfsVol, uint32 nSamples);
// call once after all data has been sent.
void Process(MixSampleInt *MixSoundBuffer, MixSampleInt *MixReverbBuffer, MixSampleInt &gnRvbROfsVol, MixSampleInt &gnRvbLOfsVol, uint32 nSamples);
private:
void Shutdown(MixSampleInt &gnRvbROfsVol, MixSampleInt &gnRvbLOfsVol);
// 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
//
struct SNDMIX_REVERB_PROPERTIES
{
int32 lRoom; // [-10000, 0] default: -10000 mB
int32 lRoomHF; // [-10000, 0] default: 0 mB
float flDecayTime; // [0.1, 20.0] default: 1.0 s
float flDecayHFRatio; // [0.1, 2.0] default: 0.5
int32 lReflections; // [-10000, 1000] default: -10000 mB
float flReflectionsDelay; // [0.0, 0.3] default: 0.02 s
int32 lReverb; // [-10000, 2000] default: -10000 mB
float flReverbDelay; // [0.0, 0.1] default: 0.04 s
float flDiffusion; // [0.0, 100.0] default: 100.0 %
float flDensity; // [0.0, 100.0] default: 100.0 %
};
enum : uint32
{
NUM_REVERBTYPES = 29
};
mpt::ustring GetReverbPresetName(uint32 preset);
const SNDMIX_REVERB_PROPERTIES *GetReverbPreset(uint32 preset);
OPENMPT_NAMESPACE_END
#endif // NO_REVERB
|