ParamEq.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * ParamEq.cpp
  3. * -----------
  4. * Purpose: Implementation of the DMO Parametric Equalizer 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. #include "stdafx.h"
  10. #ifndef NO_PLUGINS
  11. #include "../../Sndfile.h"
  12. #include "ParamEq.h"
  13. #include "mpt/base/numbers.hpp"
  14. #endif // !NO_PLUGINS
  15. OPENMPT_NAMESPACE_BEGIN
  16. #ifndef NO_PLUGINS
  17. namespace DMO
  18. {
  19. IMixPlugin* ParamEq::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  20. {
  21. return new (std::nothrow) ParamEq(factory, sndFile, mixStruct);
  22. }
  23. ParamEq::ParamEq(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  24. : IMixPlugin(factory, sndFile, mixStruct)
  25. , m_maxFreqParam(1.0f)
  26. {
  27. m_param[kEqCenter] = (8000.0f - 80.0f) / 15920.0f;
  28. m_param[kEqBandwidth] = 0.314286f;
  29. m_param[kEqGain] = 0.5f;
  30. m_mixBuffer.Initialize(2, 2);
  31. InsertIntoFactoryList();
  32. }
  33. void ParamEq::Process(float *pOutL, float *pOutR, uint32 numFrames)
  34. {
  35. if(!m_mixBuffer.Ok())
  36. return;
  37. const float *in[2] = { m_mixBuffer.GetInputBuffer(0), m_mixBuffer.GetInputBuffer(1) };
  38. float *out[2] = { m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1) };
  39. if(m_param[kEqGain] == 0.5f)
  40. {
  41. memcpy(out[0], in[0], numFrames * sizeof(float));
  42. memcpy(out[1], in[1], numFrames * sizeof(float));
  43. } else
  44. {
  45. for(uint32 i = numFrames; i != 0; i--)
  46. {
  47. for(uint8 channel = 0; channel < 2; channel++)
  48. {
  49. float x = *(in[channel])++;
  50. float y = b0DIVa0 * x + b1DIVa0 * x1[channel] + b2DIVa0 * x2[channel] - a1DIVa0 * y1[channel] - a2DIVa0 * y2[channel];
  51. x2[channel] = x1[channel];
  52. x1[channel] = x;
  53. y2[channel] = y1[channel];
  54. y1[channel] = y;
  55. *(out[channel])++ = y;
  56. }
  57. }
  58. }
  59. ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames);
  60. }
  61. PlugParamValue ParamEq::GetParameter(PlugParamIndex index)
  62. {
  63. if(index < kEqNumParameters)
  64. {
  65. return m_param[index];
  66. }
  67. return 0;
  68. }
  69. void ParamEq::SetParameter(PlugParamIndex index, PlugParamValue value)
  70. {
  71. if(index < kEqNumParameters)
  72. {
  73. value = mpt::safe_clamp(value, 0.0f, 1.0f);
  74. m_param[index] = value;
  75. RecalculateEqParams();
  76. }
  77. }
  78. void ParamEq::Resume()
  79. {
  80. m_isResumed = true;
  81. // Limit center frequency to a third of the sampling rate.
  82. m_maxFreqParam = Clamp((m_SndFile.GetSampleRate() / 3.0f - 80.0f) / 15920.0f, 0.0f, 1.0f);
  83. RecalculateEqParams();
  84. PositionChanged();
  85. }
  86. void ParamEq::PositionChanged()
  87. {
  88. // Reset filter state
  89. x1[0] = x2[0] = 0;
  90. x1[1] = x2[1] = 0;
  91. y1[0] = y2[0] = 0;
  92. y1[1] = y2[1] = 0;
  93. }
  94. #ifdef MODPLUG_TRACKER
  95. CString ParamEq::GetParamName(PlugParamIndex param)
  96. {
  97. switch(param)
  98. {
  99. case kEqCenter: return _T("Center");
  100. case kEqBandwidth: return _T("Bandwidth");
  101. case kEqGain: return _T("Gain");
  102. }
  103. return CString();
  104. }
  105. CString ParamEq::GetParamLabel(PlugParamIndex param)
  106. {
  107. switch(param)
  108. {
  109. case kEqCenter: return _T("Hz");
  110. case kEqBandwidth: return _T("Semitones");
  111. case kEqGain: return _T("dB");
  112. }
  113. return CString();
  114. }
  115. CString ParamEq::GetParamDisplay(PlugParamIndex param)
  116. {
  117. float value = 0.0f;
  118. switch(param)
  119. {
  120. case kEqCenter:
  121. value = FreqInHertz();
  122. break;
  123. case kEqBandwidth:
  124. value = BandwidthInSemitones();
  125. break;
  126. case kEqGain:
  127. value = GainInDecibel();
  128. break;
  129. }
  130. CString s;
  131. s.Format(_T("%.2f"), value);
  132. return s;
  133. }
  134. #endif // MODPLUG_TRACKER
  135. void ParamEq::RecalculateEqParams()
  136. {
  137. LimitMax(m_param[kEqCenter], m_maxFreqParam);
  138. const float freq = FreqInHertz() / m_SndFile.GetSampleRate();
  139. const float a = std::pow(10.0f, GainInDecibel() / 40.0f);
  140. const float w0 = 2.0f * mpt::numbers::pi_v<float> * freq;
  141. const float sinW0 = std::sin(w0);
  142. const float cosW0 = std::cos(w0);
  143. const float alpha = sinW0 * std::sinh((BandwidthInSemitones() * (mpt::numbers::ln2_v<float> / 24.0f)) * w0 / sinW0);
  144. const float b0 = 1.0f + alpha * a;
  145. const float b1 = -2.0f * cosW0;
  146. const float b2 = 1.0f - alpha * a;
  147. const float a0 = 1.0f + alpha / a;
  148. const float a1 = -2.0f * cosW0;
  149. const float a2 = 1.0f - alpha / a;
  150. b0DIVa0 = b0 / a0;
  151. b1DIVa0 = b1 / a0;
  152. b2DIVa0 = b2 / a0;
  153. a1DIVa0 = a1 / a0;
  154. a2DIVa0 = a2 / a0;
  155. }
  156. } // namespace DMO
  157. #else
  158. MPT_MSVC_WORKAROUND_LNK4221(ParamEq)
  159. #endif // !NO_PLUGINS
  160. OPENMPT_NAMESPACE_END