/* * ParamEq.cpp * ----------- * Purpose: Implementation of the DMO Parametric Equalizer 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 "ParamEq.h" #include "mpt/base/numbers.hpp" #endif // !NO_PLUGINS OPENMPT_NAMESPACE_BEGIN #ifndef NO_PLUGINS namespace DMO { IMixPlugin* ParamEq::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct) { return new (std::nothrow) ParamEq(factory, sndFile, mixStruct); } ParamEq::ParamEq(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct) : IMixPlugin(factory, sndFile, mixStruct) , m_maxFreqParam(1.0f) { m_param[kEqCenter] = (8000.0f - 80.0f) / 15920.0f; m_param[kEqBandwidth] = 0.314286f; m_param[kEqGain] = 0.5f; m_mixBuffer.Initialize(2, 2); InsertIntoFactoryList(); } void ParamEq::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) }; if(m_param[kEqGain] == 0.5f) { memcpy(out[0], in[0], numFrames * sizeof(float)); memcpy(out[1], in[1], numFrames * sizeof(float)); } else { for(uint32 i = numFrames; i != 0; i--) { for(uint8 channel = 0; channel < 2; channel++) { float x = *(in[channel])++; float y = b0DIVa0 * x + b1DIVa0 * x1[channel] + b2DIVa0 * x2[channel] - a1DIVa0 * y1[channel] - a2DIVa0 * y2[channel]; x2[channel] = x1[channel]; x1[channel] = x; y2[channel] = y1[channel]; y1[channel] = y; *(out[channel])++ = y; } } } ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames); } PlugParamValue ParamEq::GetParameter(PlugParamIndex index) { if(index < kEqNumParameters) { return m_param[index]; } return 0; } void ParamEq::SetParameter(PlugParamIndex index, PlugParamValue value) { if(index < kEqNumParameters) { value = mpt::safe_clamp(value, 0.0f, 1.0f); m_param[index] = value; RecalculateEqParams(); } } void ParamEq::Resume() { m_isResumed = true; // Limit center frequency to a third of the sampling rate. m_maxFreqParam = Clamp((m_SndFile.GetSampleRate() / 3.0f - 80.0f) / 15920.0f, 0.0f, 1.0f); RecalculateEqParams(); PositionChanged(); } void ParamEq::PositionChanged() { // Reset filter state x1[0] = x2[0] = 0; x1[1] = x2[1] = 0; y1[0] = y2[0] = 0; y1[1] = y2[1] = 0; } #ifdef MODPLUG_TRACKER CString ParamEq::GetParamName(PlugParamIndex param) { switch(param) { case kEqCenter: return _T("Center"); case kEqBandwidth: return _T("Bandwidth"); case kEqGain: return _T("Gain"); } return CString(); } CString ParamEq::GetParamLabel(PlugParamIndex param) { switch(param) { case kEqCenter: return _T("Hz"); case kEqBandwidth: return _T("Semitones"); case kEqGain: return _T("dB"); } return CString(); } CString ParamEq::GetParamDisplay(PlugParamIndex param) { float value = 0.0f; switch(param) { case kEqCenter: value = FreqInHertz(); break; case kEqBandwidth: value = BandwidthInSemitones(); break; case kEqGain: value = GainInDecibel(); break; } CString s; s.Format(_T("%.2f"), value); return s; } #endif // MODPLUG_TRACKER void ParamEq::RecalculateEqParams() { LimitMax(m_param[kEqCenter], m_maxFreqParam); const float freq = FreqInHertz() / m_SndFile.GetSampleRate(); const float a = std::pow(10.0f, GainInDecibel() / 40.0f); const float w0 = 2.0f * mpt::numbers::pi_v * freq; const float sinW0 = std::sin(w0); const float cosW0 = std::cos(w0); const float alpha = sinW0 * std::sinh((BandwidthInSemitones() * (mpt::numbers::ln2_v / 24.0f)) * w0 / sinW0); const float b0 = 1.0f + alpha * a; const float b1 = -2.0f * cosW0; const float b2 = 1.0f - alpha * a; const float a0 = 1.0f + alpha / a; const float a1 = -2.0f * cosW0; const float a2 = 1.0f - alpha / a; b0DIVa0 = b0 / a0; b1DIVa0 = b1 / a0; b2DIVa0 = b2 / a0; a1DIVa0 = a1 / a0; a2DIVa0 = a2 / a0; } } // namespace DMO #else MPT_MSVC_WORKAROUND_LNK4221(ParamEq) #endif // !NO_PLUGINS OPENMPT_NAMESPACE_END