Gargle.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Gargle.cpp
  3. * ----------
  4. * Purpose: Implementation of the DMO Gargle 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 "Gargle.h"
  13. #endif // !NO_PLUGINS
  14. OPENMPT_NAMESPACE_BEGIN
  15. #ifndef NO_PLUGINS
  16. namespace DMO
  17. {
  18. IMixPlugin* Gargle::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  19. {
  20. return new (std::nothrow) Gargle(factory, sndFile, mixStruct);
  21. }
  22. Gargle::Gargle(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  23. : IMixPlugin(factory, sndFile, mixStruct)
  24. {
  25. m_param[kGargleRate] = 0.02f;
  26. m_param[kGargleWaveShape] = 0.0f;
  27. m_mixBuffer.Initialize(2, 2);
  28. InsertIntoFactoryList();
  29. }
  30. void Gargle::Process(float *pOutL, float *pOutR, uint32 numFrames)
  31. {
  32. if(!m_mixBuffer.Ok())
  33. return;
  34. const float *inL = m_mixBuffer.GetInputBuffer(0), *inR = m_mixBuffer.GetInputBuffer(1);
  35. float *outL = m_mixBuffer.GetOutputBuffer(0), *outR = m_mixBuffer.GetOutputBuffer(1);
  36. const bool triangle = m_param[kGargleWaveShape] < 1.0f;
  37. for(uint32 frame = numFrames; frame != 0;)
  38. {
  39. if(m_counter < m_periodHalf)
  40. {
  41. // First half of gargle period
  42. const uint32 remain = std::min(frame, m_periodHalf - m_counter);
  43. if(triangle)
  44. {
  45. const uint32 stop = m_counter + remain;
  46. const float factor = 1.0f / m_periodHalf;
  47. for(uint32 i = m_counter; i < stop; i++)
  48. {
  49. *outL++ = *inL++ * i * factor;
  50. *outR++ = *inR++ * i * factor;
  51. }
  52. } else
  53. {
  54. for(uint32 i = 0; i < remain; i++)
  55. {
  56. *outL++ = *inL++;
  57. *outR++ = *inR++;
  58. }
  59. }
  60. frame -= remain;
  61. m_counter += remain;
  62. } else
  63. {
  64. // Second half of gargle period
  65. const uint32 remain = std::min(frame, m_period - m_counter);
  66. if(triangle)
  67. {
  68. const uint32 stop = m_period - m_counter - remain;
  69. const float factor = 1.0f / m_periodHalf;
  70. for(uint32 i = m_period - m_counter; i > stop; i--)
  71. {
  72. *outL++ = *inL++ * i * factor;
  73. *outR++ = *inR++ * i * factor;
  74. }
  75. } else
  76. {
  77. for(uint32 i = 0; i < remain; i++)
  78. {
  79. *outL++ = 0;
  80. *outR++ = 0;
  81. }
  82. inL += remain;
  83. inR += remain;
  84. }
  85. frame -= remain;
  86. m_counter += remain;
  87. if(m_counter >= m_period) m_counter = 0;
  88. }
  89. }
  90. ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames);
  91. }
  92. PlugParamValue Gargle::GetParameter(PlugParamIndex index)
  93. {
  94. if(index < kGargleNumParameters)
  95. {
  96. return m_param[index];
  97. }
  98. return 0;
  99. }
  100. void Gargle::SetParameter(PlugParamIndex index, PlugParamValue value)
  101. {
  102. if(index < kGargleNumParameters)
  103. {
  104. value = mpt::safe_clamp(value, 0.0f, 1.0f);
  105. if(index == kGargleWaveShape)
  106. value = mpt::round(value);
  107. m_param[index] = value;
  108. RecalculateGargleParams();
  109. }
  110. }
  111. void Gargle::Resume()
  112. {
  113. RecalculateGargleParams();
  114. m_counter = 0;
  115. m_isResumed = true;
  116. }
  117. #ifdef MODPLUG_TRACKER
  118. CString Gargle::GetParamName(PlugParamIndex param)
  119. {
  120. switch(param)
  121. {
  122. case kGargleRate: return _T("Rate");
  123. case kGargleWaveShape: return _T("WaveShape");
  124. }
  125. return CString();
  126. }
  127. CString Gargle::GetParamLabel(PlugParamIndex param)
  128. {
  129. switch(param)
  130. {
  131. case kGargleRate: return _T("Hz");
  132. }
  133. return CString();
  134. }
  135. CString Gargle::GetParamDisplay(PlugParamIndex param)
  136. {
  137. CString s;
  138. switch(param)
  139. {
  140. case kGargleRate:
  141. s.Format(_T("%u"), RateInHertz());
  142. break;
  143. case kGargleWaveShape:
  144. return (m_param[param] < 0.5) ? _T("Triangle") : _T("Square");
  145. }
  146. return s;
  147. }
  148. #endif // MODPLUG_TRACKER
  149. uint32 Gargle::RateInHertz() const
  150. {
  151. return static_cast<uint32>(mpt::round(std::clamp(m_param[kGargleRate], 0.0f, 1.0f) * 999.0f)) + 1;
  152. }
  153. void Gargle::RecalculateGargleParams()
  154. {
  155. m_period = m_SndFile.GetSampleRate() / RateInHertz();
  156. if(m_period < 2) m_period = 2;
  157. m_periodHalf = m_period / 2;
  158. LimitMax(m_counter, m_period);
  159. }
  160. } // namespace DMO
  161. #else
  162. MPT_MSVC_WORKAROUND_LNK4221(Gargle)
  163. #endif // !NO_PLUGINS
  164. OPENMPT_NAMESPACE_END