1 /*
2  * I3DL2Reverb.h
3  * -------------
4  * Purpose: Implementation of the DMO I3DL2Reverb DSP (for non-Windows platforms)
5  * Notes  : (currently none)
6  * Authors: OpenMPT Devs
7  * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
8  */
9 
10 
11 #pragma once
12 
13 #include "openmpt/all/BuildSettings.hpp"
14 
15 #ifndef NO_PLUGINS
16 
17 #include "../PlugInterface.h"
18 
19 OPENMPT_NAMESPACE_BEGIN
20 
21 namespace DMO
22 {
23 
24 class I3DL2Reverb final : public IMixPlugin
25 {
26 protected:
27 	enum Parameters
28 	{
29 		kI3DL2ReverbRoom = 0,
30 		kI3DL2ReverbRoomHF,
31 		kI3DL2ReverbRoomRolloffFactor,	// Doesn't actually do anything :)
32 		kI3DL2ReverbDecayTime,
33 		kI3DL2ReverbDecayHFRatio,
34 		kI3DL2ReverbReflections,
35 		kI3DL2ReverbReflectionsDelay,
36 		kI3DL2ReverbReverb,
37 		kI3DL2ReverbReverbDelay,
38 		kI3DL2ReverbDiffusion,
39 		kI3DL2ReverbDensity,
40 		kI3DL2ReverbHFReference,
41 		kI3DL2ReverbQuality,
42 		kI3DL2ReverbNumParameters
43 	};
44 
45 	enum QualityFlags
46 	{
47 		kMoreDelayLines = 0x01,
48 		kFullSampleRate = 0x02,
49 	};
50 
51 	class DelayLine : private std::vector<float>
52 	{
53 		int32 m_length;
54 		int32 m_position;
55 		int32 m_delayPosition;
56 
57 	public:
58 		void Init(int32 ms, int32 padding, uint32 sampleRate, int32 delayTap = 0);
59 		void SetDelayTap(int32 delayTap);
60 		void Advance();
61 		void Set(float value);
62 		float Get(int32 offset) const;
63 		float Get() const;
64 	};
65 
66 	float m_param[kI3DL2ReverbNumParameters];
67 	int32 m_program = 0;
68 
69 	// Calculated parameters
70 	uint32 m_quality;
71 	float m_effectiveSampleRate;
72 	float m_diffusion;
73 	float m_roomFilter;
74 	float m_ERLevel;
75 	float m_ReverbLevelL;
76 	float m_ReverbLevelR;
77 
78 	int32 m_delayTaps[15];	// 6*L + 6*R + LR + Early L + Early R
79 	int32 m_earlyTaps[2][6];
80 	float m_delayCoeffs[13][2];
81 
82 	// State
83 	DelayLine m_delayLines[19];
84 	float m_filterHist[19];
85 
86 	// Remaining frame for downsampled reverb
87 	float m_prevL;
88 	float m_prevR;
89 	bool m_remain = false;
90 
91 	bool m_ok = false, m_recalcParams = true;
92 
93 public:
94 	static IMixPlugin* Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
95 	I3DL2Reverb(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
96 
Release()97 	void Release() override { delete this; }
GetUID()98 	int32 GetUID() const override { return 0xEF985E71; }
GetVersion()99 	int32 GetVersion() const override { return 0; }
Idle()100 	void Idle() override { }
GetLatency()101 	uint32 GetLatency() const override { return 0; }
102 
103 	void Process(float *pOutL, float *pOutR, uint32 numFrames) override;
104 
RenderSilence(uint32)105 	float RenderSilence(uint32) override { return 0.0f; }
106 
107 	int32 GetNumPrograms() const override;
GetCurrentProgram()108 	int32 GetCurrentProgram() override { return m_program; }
109 	// cppcheck-suppress virtualCallInConstructor
110 	void SetCurrentProgram(int32) override;
111 
GetNumParameters()112 	PlugParamIndex GetNumParameters() const override { return kI3DL2ReverbNumParameters; }
113 	PlugParamValue GetParameter(PlugParamIndex index) override;
114 	void SetParameter(PlugParamIndex index, PlugParamValue value) override;
115 
116 	void Resume() override;
Suspend()117 	void Suspend() override { m_isResumed = false; }
118 	void PositionChanged() override;
IsInstrument()119 	bool IsInstrument() const override { return false; }
CanRecieveMidiEvents()120 	bool CanRecieveMidiEvents() override { return false; }
ShouldProcessSilence()121 	bool ShouldProcessSilence() override { return true; }
122 
123 #ifdef MODPLUG_TRACKER
GetDefaultEffectName()124 	CString GetDefaultEffectName() override { return _T("I3DL2Reverb"); }
125 
126 	CString GetParamName(PlugParamIndex param) override;
127 	CString GetParamLabel(PlugParamIndex) override;
128 	CString GetParamDisplay(PlugParamIndex param) override;
129 
130 	CString GetCurrentProgramName() override;
SetCurrentProgramName(const CString &)131 	void SetCurrentProgramName(const CString &) override { }
132 	CString GetProgramName(int32 program) override;
133 
HasEditor()134 	bool HasEditor() const override { return false; }
135 #endif
136 
BeginSetProgram(int32)137 	void BeginSetProgram(int32) override { }
EndSetProgram()138 	void EndSetProgram() override { }
139 
GetNumInputChannels()140 	int GetNumInputChannels() const override { return 2; }
GetNumOutputChannels()141 	int GetNumOutputChannels() const override { return 2; }
142 
143 protected:
Room()144 	float Room() const { return -10000.0f + m_param[kI3DL2ReverbRoom] * 10000.0f; }
RoomHF()145 	float RoomHF() const { return -10000.0f + m_param[kI3DL2ReverbRoomHF] * 10000.0f; }
RoomRolloffFactor()146 	float RoomRolloffFactor() const { return m_param[kI3DL2ReverbRoomRolloffFactor] * 10.0f; }
DecayTime()147 	float DecayTime() const { return 0.1f + m_param[kI3DL2ReverbDecayTime] * 19.9f; }
DecayHFRatio()148 	float DecayHFRatio() const { return 0.1f + m_param[kI3DL2ReverbDecayHFRatio] * 1.9f; }
Reflections()149 	float Reflections() const { return -10000.0f + m_param[kI3DL2ReverbReflections] * 11000.0f; }
ReflectionsDelay()150 	float ReflectionsDelay() const { return m_param[kI3DL2ReverbReflectionsDelay] * 0.3f; }
Reverb()151 	float Reverb() const { return -10000.0f + m_param[kI3DL2ReverbReverb] * 12000.0f; }
ReverbDelay()152 	float ReverbDelay() const { return m_param[kI3DL2ReverbReverbDelay] * 0.1f; }
Diffusion()153 	float Diffusion() const { return m_param[kI3DL2ReverbDiffusion] * 100.0f; }
Density()154 	float Density() const { return m_param[kI3DL2ReverbDensity] * 100.0f; }
HFReference()155 	float HFReference() const { return 20.0f + m_param[kI3DL2ReverbHFReference] * 19980.0f; }
Quality()156 	uint32 Quality() const { return mpt::saturate_round<uint32>(m_param[kI3DL2ReverbQuality] * 3.0f); }
157 
158 	void RecalculateI3DL2ReverbParams();
159 
160 	void SetDelayTaps();
161 	void SetDecayCoeffs();
162 	float CalcDecayCoeffs(int32 index);
163 };
164 
165 } // namespace DMO
166 
167 OPENMPT_NAMESPACE_END
168 
169 #endif // !NO_PLUGINS
170