123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- * WavesReverb.cpp
- * ---------------
- * Purpose: Implementation of the DMO WavesReverb 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.
- */
- #include "stdafx.h"
- #ifndef NO_PLUGINS
- #include "../../Sndfile.h"
- #include "WavesReverb.h"
- #endif // !NO_PLUGINS
- OPENMPT_NAMESPACE_BEGIN
- #ifndef NO_PLUGINS
- namespace DMO
- {
- IMixPlugin* WavesReverb::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
- {
- return new (std::nothrow) WavesReverb(factory, sndFile, mixStruct);
- }
- WavesReverb::WavesReverb(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
- : IMixPlugin(factory, sndFile, mixStruct)
- {
- m_param[kRvbInGain] = 1.0f;
- m_param[kRvbReverbMix] = 1.0f;
- m_param[kRvbReverbTime] = 1.0f / 3.0f;
- m_param[kRvbHighFreqRTRatio] = 0.0f;
- m_mixBuffer.Initialize(2, 2);
- InsertIntoFactoryList();
- }
- void WavesReverb::Process(float *pOutL, float *pOutR, uint32 numFrames)
- {
- if(!m_mixBuffer.Ok())
- return;
- const float *in[2] = { m_mixBuffer.GetInputBuffer(0), m_mixBuffer.GetInputBuffer(1) };
- float *out[2] = { m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1) };
- uint32 combPos = m_state.combPos, allpassPos = m_state.allpassPos;
- uint32 delay0 = (m_delay[0] + combPos + 1) & 0xFFF;
- uint32 delay1 = (m_delay[1] + combPos + 1) & 0xFFF;
- uint32 delay2 = (m_delay[2] + combPos + 1) & 0xFFF;
- uint32 delay3 = (m_delay[3] + combPos + 1) & 0xFFF;
- uint32 delay4 = (m_delay[4] + allpassPos) & 0x3FF;
- uint32 delay5 = (m_delay[5] + allpassPos) & 0x3FF;
- float delay0old = m_state.comb[delay0][0];
- float delay1old = m_state.comb[delay1][1];
- float delay2old = m_state.comb[delay2][2];
- float delay3old = m_state.comb[delay3][3];
- for(uint32 i = numFrames; i != 0; i--)
- {
- const float leftIn = *(in[0])++ + 1e-30f; // Prevent denormals
- const float rightIn = *(in[1])++ + 1e-30f; // Prevent denormals
- // Advance buffer index for the four comb filters
- delay0 = (delay0 - 1) & 0xFFF;
- delay1 = (delay1 - 1) & 0xFFF;
- delay2 = (delay2 - 1) & 0xFFF;
- delay3 = (delay3 - 1) & 0xFFF;
- float &delay0new = m_state.comb[delay0][0];
- float &delay1new = m_state.comb[delay1][1];
- float &delay2new = m_state.comb[delay2][2];
- float &delay3new = m_state.comb[delay3][3];
- float r1, r2;
-
- r1 = delay1new * 0.61803401f + m_state.allpass1[delay4][0] * m_coeffs[0];
- r2 = m_state.allpass1[delay4][1] * m_coeffs[0] - delay0new * 0.61803401f;
- m_state.allpass1[allpassPos][0] = r2 * 0.61803401f + delay0new;
- m_state.allpass1[allpassPos][1] = delay1new - r1 * 0.61803401f;
- delay0new = r1;
- delay1new = r2;
- r1 = delay3new * 0.61803401f + m_state.allpass2[delay5][0] * m_coeffs[1];
- r2 = m_state.allpass2[delay5][1] * m_coeffs[1] - delay2new * 0.61803401f;
- m_state.allpass2[allpassPos][0] = r2 * 0.61803401f + delay2new;
- m_state.allpass2[allpassPos][1] = delay3new - r1 * 0.61803401f;
- delay2new = r1;
- delay3new = r2;
- *(out[0])++ = (leftIn * m_dryFactor) + delay0new + delay2new;
- *(out[1])++ = (rightIn * m_dryFactor) + delay1new + delay3new;
- const float leftWet = leftIn * m_wetFactor;
- const float rightWet = rightIn * m_wetFactor;
- m_state.comb[combPos][0] = (delay0new * m_coeffs[2]) + (delay0old * m_coeffs[3]) + leftWet;
- m_state.comb[combPos][1] = (delay1new * m_coeffs[4]) + (delay1old * m_coeffs[5]) + rightWet;
- m_state.comb[combPos][2] = (delay2new * m_coeffs[6]) + (delay2old * m_coeffs[7]) - rightWet;
- m_state.comb[combPos][3] = (delay3new * m_coeffs[8]) + (delay3old * m_coeffs[9]) + leftWet;
- delay0old = delay0new;
- delay1old = delay1new;
- delay2old = delay2new;
- delay3old = delay3new;
- // Advance buffer index
- combPos = (combPos - 1) & 0xFFF;
- allpassPos = (allpassPos - 1) & 0x3FF;
- delay4 = (delay4 - 1) & 0x3FF;
- delay5 = (delay5 - 1) & 0x3FF;
- }
- m_state.combPos = combPos;
- m_state.allpassPos = allpassPos;
- ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames);
- }
- PlugParamValue WavesReverb::GetParameter(PlugParamIndex index)
- {
- if(index < kRvbNumParameters)
- {
- return m_param[index];
- }
- return 0;
- }
- void WavesReverb::SetParameter(PlugParamIndex index, PlugParamValue value)
- {
- if(index < kRvbNumParameters)
- {
- value = mpt::safe_clamp(value, 0.0f, 1.0f);
- m_param[index] = value;
- RecalculateWavesReverbParams();
- }
- }
- void WavesReverb::Resume()
- {
- m_isResumed = true;
- // Recalculate delays
- uint32 delay0 = mpt::saturate_round<uint32>(m_SndFile.GetSampleRate() * 0.045f);
- uint32 delay1 = mpt::saturate_round<uint32>(delay0 * 1.18920707f); // 2^0.25
- uint32 delay2 = mpt::saturate_round<uint32>(delay1 * 1.18920707f);
- uint32 delay3 = mpt::saturate_round<uint32>(delay2 * 1.18920707f);
- uint32 delay4 = mpt::saturate_round<uint32>((delay0 + delay2) * 0.11546667f);
- uint32 delay5 = mpt::saturate_round<uint32>((delay1 + delay3) * 0.11546667f);
- // Comb delays
- m_delay[0] = delay0 - delay4;
- m_delay[1] = delay2 - delay4;
- m_delay[2] = delay1 - delay5;
- m_delay[3] = delay3 - delay5;
- // Allpass delays
- m_delay[4] = delay4;
- m_delay[5] = delay5;
- RecalculateWavesReverbParams();
- PositionChanged();
- }
- void WavesReverb::PositionChanged()
- {
- MemsetZero(m_state);
- }
- #ifdef MODPLUG_TRACKER
- CString WavesReverb::GetParamName(PlugParamIndex param)
- {
- switch(param)
- {
- case kRvbInGain: return _T("InGain");
- case kRvbReverbMix: return _T("ReverbMix");
- case kRvbReverbTime: return _T("ReverbTime");
- case kRvbHighFreqRTRatio: return _T("HighFreqRTRatio");
- }
- return CString();
- }
- CString WavesReverb::GetParamLabel(PlugParamIndex param)
- {
- switch(param)
- {
- case kRvbInGain:
- case kRvbReverbMix:
- return _T("dB");
- case kRvbReverbTime:
- return _T("ms");
- }
- return CString();
- }
- CString WavesReverb::GetParamDisplay(PlugParamIndex param)
- {
- float value = m_param[param];
- switch(param)
- {
- case kRvbInGain:
- case kRvbReverbMix:
- value = GainInDecibel(value);
- break;
- case kRvbReverbTime:
- value = ReverbTime();
- break;
- case kRvbHighFreqRTRatio:
- value = HighFreqRTRatio();
- break;
- }
- CString s;
- s.Format(_T("%.2f"), value);
- return s;
- }
- #endif // MODPLUG_TRACKER
- void WavesReverb::RecalculateWavesReverbParams()
- {
- // Recalculate filters
- const double ReverbTimeSmp = -3000.0 / (m_SndFile.GetSampleRate() * ReverbTime());
- const double ReverbTimeSmpHF = ReverbTimeSmp * (1.0 / HighFreqRTRatio() - 1.0);
- m_coeffs[0] = static_cast<float>(std::pow(10.0, m_delay[4] * ReverbTimeSmp));
- m_coeffs[1] = static_cast<float>(std::pow(10.0, m_delay[5] * ReverbTimeSmp));
- double sum = 0.0;
- for(uint32 pair = 0; pair < 4; pair++)
- {
- double gain1 = std::pow(10.0, m_delay[pair] * ReverbTimeSmp);
- double gain2 = (1.0 - std::pow(10.0, (m_delay[pair] + m_delay[4 + pair / 2]) * ReverbTimeSmpHF)) * 0.5;
- double gain3 = gain1 * m_coeffs[pair / 2];
- double gain4 = gain3 * (((gain3 + 1.0) * gain3 + 1.0) * gain3 + 1.0) + 1.0;
- m_coeffs[2 + pair * 2] = static_cast<float>(gain1 * (1.0 - gain2));
- m_coeffs[3 + pair * 2] = static_cast<float>(gain1 * gain2);
- sum += gain4 * gain4;
- }
- double inGain = std::pow(10.0, GainInDecibel(m_param[kRvbInGain]) * 0.05);
- double reverbMix = std::pow(10.0, GainInDecibel(m_param[kRvbReverbMix]) * 0.1);
- m_dryFactor = static_cast<float>(std::sqrt(1.0 - reverbMix) * inGain);
- m_wetFactor = static_cast<float>(std::sqrt(reverbMix) * (4.0 / std::sqrt(sum) * inGain));
- }
- } // namespace DMO
- #else
- MPT_MSVC_WORKAROUND_LNK4221(WavesReverb)
- #endif // !NO_PLUGINS
- OPENMPT_NAMESPACE_END
|