mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-13 14:01:01 -05:00
202 lines
4.2 KiB
C++
202 lines
4.2 KiB
C++
|
/*
|
||
|
* 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
|