123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- /*
- * 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<float> * freq;
- const float sinW0 = std::sin(w0);
- const float cosW0 = std::cos(w0);
- const float alpha = sinW0 * std::sinh((BandwidthInSemitones() * (mpt::numbers::ln2_v<float> / 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
|