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
|
/*
* I3DL2Reverb.h
* -------------
* Purpose: Implementation of the DMO I3DL2Reverb DSP (for non-Windows platforms)
* Notes : (currently none)
* Authors: 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_PLUGINS
#include "../PlugInterface.h"
OPENMPT_NAMESPACE_BEGIN
namespace DMO
{
class I3DL2Reverb final : public IMixPlugin
{
protected:
enum Parameters
{
kI3DL2ReverbRoom = 0,
kI3DL2ReverbRoomHF,
kI3DL2ReverbRoomRolloffFactor, // Doesn't actually do anything :)
kI3DL2ReverbDecayTime,
kI3DL2ReverbDecayHFRatio,
kI3DL2ReverbReflections,
kI3DL2ReverbReflectionsDelay,
kI3DL2ReverbReverb,
kI3DL2ReverbReverbDelay,
kI3DL2ReverbDiffusion,
kI3DL2ReverbDensity,
kI3DL2ReverbHFReference,
kI3DL2ReverbQuality,
kI3DL2ReverbNumParameters
};
enum QualityFlags
{
kMoreDelayLines = 0x01,
kFullSampleRate = 0x02,
};
class DelayLine : private std::vector<float>
{
int32 m_length;
int32 m_position;
int32 m_delayPosition;
public:
void Init(int32 ms, int32 padding, uint32 sampleRate, int32 delayTap = 0);
void SetDelayTap(int32 delayTap);
void Advance();
void Set(float value);
float Get(int32 offset) const;
float Get() const;
};
std::array<float, kI3DL2ReverbNumParameters> m_param;
int32 m_program = 0;
// Calculated parameters
uint32 m_quality;
float m_effectiveSampleRate;
float m_diffusion;
float m_roomFilter;
float m_ERLevel;
float m_ReverbLevelL;
float m_ReverbLevelR;
int32 m_delayTaps[15]; // 6*L + 6*R + LR + Early L + Early R
int32 m_earlyTaps[2][6];
float m_delayCoeffs[13][2];
// State
DelayLine m_delayLines[19];
float m_filterHist[19];
// Remaining frame for downsampled reverb
float m_prevL;
float m_prevR;
bool m_remain = false;
bool m_ok = false, m_recalcParams = true;
public:
static IMixPlugin* Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
I3DL2Reverb(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
void Release() override { delete this; }
int32 GetUID() const override { return 0xEF985E71; }
int32 GetVersion() const override { return 0; }
void Idle() override { }
uint32 GetLatency() const override { return 0; }
void Process(float *pOutL, float *pOutR, uint32 numFrames) override;
float RenderSilence(uint32) override { return 0.0f; }
int32 GetNumPrograms() const override;
int32 GetCurrentProgram() override { return m_program; }
// cppcheck-suppress virtualCallInConstructor
void SetCurrentProgram(int32) override;
PlugParamIndex GetNumParameters() const override { return kI3DL2ReverbNumParameters; }
PlugParamValue GetParameter(PlugParamIndex index) override;
void SetParameter(PlugParamIndex index, PlugParamValue value) override;
void Resume() override;
void Suspend() override { m_isResumed = false; }
void PositionChanged() override;
bool IsInstrument() const override { return false; }
bool CanRecieveMidiEvents() override { return false; }
bool ShouldProcessSilence() override { return true; }
#ifdef MODPLUG_TRACKER
CString GetDefaultEffectName() override { return _T("I3DL2Reverb"); }
CString GetParamName(PlugParamIndex param) override;
CString GetParamLabel(PlugParamIndex) override;
CString GetParamDisplay(PlugParamIndex param) override;
CString GetCurrentProgramName() override;
void SetCurrentProgramName(const CString &) override { }
CString GetProgramName(int32 program) override;
bool HasEditor() const override { return false; }
#endif
void BeginSetProgram(int32) override { }
void EndSetProgram() override { }
int GetNumInputChannels() const override { return 2; }
int GetNumOutputChannels() const override { return 2; }
protected:
float Room() const { return -10000.0f + m_param[kI3DL2ReverbRoom] * 10000.0f; }
float RoomHF() const { return -10000.0f + m_param[kI3DL2ReverbRoomHF] * 10000.0f; }
float RoomRolloffFactor() const { return m_param[kI3DL2ReverbRoomRolloffFactor] * 10.0f; }
float DecayTime() const { return 0.1f + m_param[kI3DL2ReverbDecayTime] * 19.9f; }
float DecayHFRatio() const { return 0.1f + m_param[kI3DL2ReverbDecayHFRatio] * 1.9f; }
float Reflections() const { return -10000.0f + m_param[kI3DL2ReverbReflections] * 11000.0f; }
float ReflectionsDelay() const { return m_param[kI3DL2ReverbReflectionsDelay] * 0.3f; }
float Reverb() const { return -10000.0f + m_param[kI3DL2ReverbReverb] * 12000.0f; }
float ReverbDelay() const { return m_param[kI3DL2ReverbReverbDelay] * 0.1f; }
float Diffusion() const { return m_param[kI3DL2ReverbDiffusion] * 100.0f; }
float Density() const { return m_param[kI3DL2ReverbDensity] * 100.0f; }
float HFReference() const { return 20.0f + m_param[kI3DL2ReverbHFReference] * 19980.0f; }
uint32 Quality() const { return mpt::saturate_round<uint32>(m_param[kI3DL2ReverbQuality] * 3.0f); }
void RecalculateI3DL2ReverbParams();
void SetDelayTaps();
void SetDecayCoeffs();
float CalcDecayCoeffs(int32 index);
};
} // namespace DMO
OPENMPT_NAMESPACE_END
#endif // !NO_PLUGINS
|