WavesReverb.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * WavesReverb.cpp
  3. * ---------------
  4. * Purpose: Implementation of the DMO WavesReverb 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 "WavesReverb.h"
  13. #endif // !NO_PLUGINS
  14. OPENMPT_NAMESPACE_BEGIN
  15. #ifndef NO_PLUGINS
  16. namespace DMO
  17. {
  18. IMixPlugin* WavesReverb::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  19. {
  20. return new (std::nothrow) WavesReverb(factory, sndFile, mixStruct);
  21. }
  22. WavesReverb::WavesReverb(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
  23. : IMixPlugin(factory, sndFile, mixStruct)
  24. {
  25. m_param[kRvbInGain] = 1.0f;
  26. m_param[kRvbReverbMix] = 1.0f;
  27. m_param[kRvbReverbTime] = 1.0f / 3.0f;
  28. m_param[kRvbHighFreqRTRatio] = 0.0f;
  29. m_mixBuffer.Initialize(2, 2);
  30. InsertIntoFactoryList();
  31. }
  32. void WavesReverb::Process(float *pOutL, float *pOutR, uint32 numFrames)
  33. {
  34. if(!m_mixBuffer.Ok())
  35. return;
  36. const float *in[2] = { m_mixBuffer.GetInputBuffer(0), m_mixBuffer.GetInputBuffer(1) };
  37. float *out[2] = { m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1) };
  38. uint32 combPos = m_state.combPos, allpassPos = m_state.allpassPos;
  39. uint32 delay0 = (m_delay[0] + combPos + 1) & 0xFFF;
  40. uint32 delay1 = (m_delay[1] + combPos + 1) & 0xFFF;
  41. uint32 delay2 = (m_delay[2] + combPos + 1) & 0xFFF;
  42. uint32 delay3 = (m_delay[3] + combPos + 1) & 0xFFF;
  43. uint32 delay4 = (m_delay[4] + allpassPos) & 0x3FF;
  44. uint32 delay5 = (m_delay[5] + allpassPos) & 0x3FF;
  45. float delay0old = m_state.comb[delay0][0];
  46. float delay1old = m_state.comb[delay1][1];
  47. float delay2old = m_state.comb[delay2][2];
  48. float delay3old = m_state.comb[delay3][3];
  49. for(uint32 i = numFrames; i != 0; i--)
  50. {
  51. const float leftIn = *(in[0])++ + 1e-30f; // Prevent denormals
  52. const float rightIn = *(in[1])++ + 1e-30f; // Prevent denormals
  53. // Advance buffer index for the four comb filters
  54. delay0 = (delay0 - 1) & 0xFFF;
  55. delay1 = (delay1 - 1) & 0xFFF;
  56. delay2 = (delay2 - 1) & 0xFFF;
  57. delay3 = (delay3 - 1) & 0xFFF;
  58. float &delay0new = m_state.comb[delay0][0];
  59. float &delay1new = m_state.comb[delay1][1];
  60. float &delay2new = m_state.comb[delay2][2];
  61. float &delay3new = m_state.comb[delay3][3];
  62. float r1, r2;
  63. r1 = delay1new * 0.61803401f + m_state.allpass1[delay4][0] * m_coeffs[0];
  64. r2 = m_state.allpass1[delay4][1] * m_coeffs[0] - delay0new * 0.61803401f;
  65. m_state.allpass1[allpassPos][0] = r2 * 0.61803401f + delay0new;
  66. m_state.allpass1[allpassPos][1] = delay1new - r1 * 0.61803401f;
  67. delay0new = r1;
  68. delay1new = r2;
  69. r1 = delay3new * 0.61803401f + m_state.allpass2[delay5][0] * m_coeffs[1];
  70. r2 = m_state.allpass2[delay5][1] * m_coeffs[1] - delay2new * 0.61803401f;
  71. m_state.allpass2[allpassPos][0] = r2 * 0.61803401f + delay2new;
  72. m_state.allpass2[allpassPos][1] = delay3new - r1 * 0.61803401f;
  73. delay2new = r1;
  74. delay3new = r2;
  75. *(out[0])++ = (leftIn * m_dryFactor) + delay0new + delay2new;
  76. *(out[1])++ = (rightIn * m_dryFactor) + delay1new + delay3new;
  77. const float leftWet = leftIn * m_wetFactor;
  78. const float rightWet = rightIn * m_wetFactor;
  79. m_state.comb[combPos][0] = (delay0new * m_coeffs[2]) + (delay0old * m_coeffs[3]) + leftWet;
  80. m_state.comb[combPos][1] = (delay1new * m_coeffs[4]) + (delay1old * m_coeffs[5]) + rightWet;
  81. m_state.comb[combPos][2] = (delay2new * m_coeffs[6]) + (delay2old * m_coeffs[7]) - rightWet;
  82. m_state.comb[combPos][3] = (delay3new * m_coeffs[8]) + (delay3old * m_coeffs[9]) + leftWet;
  83. delay0old = delay0new;
  84. delay1old = delay1new;
  85. delay2old = delay2new;
  86. delay3old = delay3new;
  87. // Advance buffer index
  88. combPos = (combPos - 1) & 0xFFF;
  89. allpassPos = (allpassPos - 1) & 0x3FF;
  90. delay4 = (delay4 - 1) & 0x3FF;
  91. delay5 = (delay5 - 1) & 0x3FF;
  92. }
  93. m_state.combPos = combPos;
  94. m_state.allpassPos = allpassPos;
  95. ProcessMixOps(pOutL, pOutR, m_mixBuffer.GetOutputBuffer(0), m_mixBuffer.GetOutputBuffer(1), numFrames);
  96. }
  97. PlugParamValue WavesReverb::GetParameter(PlugParamIndex index)
  98. {
  99. if(index < kRvbNumParameters)
  100. {
  101. return m_param[index];
  102. }
  103. return 0;
  104. }
  105. void WavesReverb::SetParameter(PlugParamIndex index, PlugParamValue value)
  106. {
  107. if(index < kRvbNumParameters)
  108. {
  109. value = mpt::safe_clamp(value, 0.0f, 1.0f);
  110. m_param[index] = value;
  111. RecalculateWavesReverbParams();
  112. }
  113. }
  114. void WavesReverb::Resume()
  115. {
  116. m_isResumed = true;
  117. // Recalculate delays
  118. uint32 delay0 = mpt::saturate_round<uint32>(m_SndFile.GetSampleRate() * 0.045f);
  119. uint32 delay1 = mpt::saturate_round<uint32>(delay0 * 1.18920707f); // 2^0.25
  120. uint32 delay2 = mpt::saturate_round<uint32>(delay1 * 1.18920707f);
  121. uint32 delay3 = mpt::saturate_round<uint32>(delay2 * 1.18920707f);
  122. uint32 delay4 = mpt::saturate_round<uint32>((delay0 + delay2) * 0.11546667f);
  123. uint32 delay5 = mpt::saturate_round<uint32>((delay1 + delay3) * 0.11546667f);
  124. // Comb delays
  125. m_delay[0] = delay0 - delay4;
  126. m_delay[1] = delay2 - delay4;
  127. m_delay[2] = delay1 - delay5;
  128. m_delay[3] = delay3 - delay5;
  129. // Allpass delays
  130. m_delay[4] = delay4;
  131. m_delay[5] = delay5;
  132. RecalculateWavesReverbParams();
  133. PositionChanged();
  134. }
  135. void WavesReverb::PositionChanged()
  136. {
  137. MemsetZero(m_state);
  138. }
  139. #ifdef MODPLUG_TRACKER
  140. CString WavesReverb::GetParamName(PlugParamIndex param)
  141. {
  142. switch(param)
  143. {
  144. case kRvbInGain: return _T("InGain");
  145. case kRvbReverbMix: return _T("ReverbMix");
  146. case kRvbReverbTime: return _T("ReverbTime");
  147. case kRvbHighFreqRTRatio: return _T("HighFreqRTRatio");
  148. }
  149. return CString();
  150. }
  151. CString WavesReverb::GetParamLabel(PlugParamIndex param)
  152. {
  153. switch(param)
  154. {
  155. case kRvbInGain:
  156. case kRvbReverbMix:
  157. return _T("dB");
  158. case kRvbReverbTime:
  159. return _T("ms");
  160. }
  161. return CString();
  162. }
  163. CString WavesReverb::GetParamDisplay(PlugParamIndex param)
  164. {
  165. float value = m_param[param];
  166. switch(param)
  167. {
  168. case kRvbInGain:
  169. case kRvbReverbMix:
  170. value = GainInDecibel(value);
  171. break;
  172. case kRvbReverbTime:
  173. value = ReverbTime();
  174. break;
  175. case kRvbHighFreqRTRatio:
  176. value = HighFreqRTRatio();
  177. break;
  178. }
  179. CString s;
  180. s.Format(_T("%.2f"), value);
  181. return s;
  182. }
  183. #endif // MODPLUG_TRACKER
  184. void WavesReverb::RecalculateWavesReverbParams()
  185. {
  186. // Recalculate filters
  187. const double ReverbTimeSmp = -3000.0 / (m_SndFile.GetSampleRate() * ReverbTime());
  188. const double ReverbTimeSmpHF = ReverbTimeSmp * (1.0 / HighFreqRTRatio() - 1.0);
  189. m_coeffs[0] = static_cast<float>(std::pow(10.0, m_delay[4] * ReverbTimeSmp));
  190. m_coeffs[1] = static_cast<float>(std::pow(10.0, m_delay[5] * ReverbTimeSmp));
  191. double sum = 0.0;
  192. for(uint32 pair = 0; pair < 4; pair++)
  193. {
  194. double gain1 = std::pow(10.0, m_delay[pair] * ReverbTimeSmp);
  195. double gain2 = (1.0 - std::pow(10.0, (m_delay[pair] + m_delay[4 + pair / 2]) * ReverbTimeSmpHF)) * 0.5;
  196. double gain3 = gain1 * m_coeffs[pair / 2];
  197. double gain4 = gain3 * (((gain3 + 1.0) * gain3 + 1.0) * gain3 + 1.0) + 1.0;
  198. m_coeffs[2 + pair * 2] = static_cast<float>(gain1 * (1.0 - gain2));
  199. m_coeffs[3 + pair * 2] = static_cast<float>(gain1 * gain2);
  200. sum += gain4 * gain4;
  201. }
  202. double inGain = std::pow(10.0, GainInDecibel(m_param[kRvbInGain]) * 0.05);
  203. double reverbMix = std::pow(10.0, GainInDecibel(m_param[kRvbReverbMix]) * 0.1);
  204. m_dryFactor = static_cast<float>(std::sqrt(1.0 - reverbMix) * inGain);
  205. m_wetFactor = static_cast<float>(std::sqrt(reverbMix) * (4.0 / std::sqrt(sum) * inGain));
  206. }
  207. } // namespace DMO
  208. #else
  209. MPT_MSVC_WORKAROUND_LNK4221(WavesReverb)
  210. #endif // !NO_PLUGINS
  211. OPENMPT_NAMESPACE_END