You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.3KB

  1. /***************************************************/
  2. /*! \class PRCRev
  3. \brief Perry's simple reverberator class.
  4. This class is based on some of the famous
  5. Stanford/CCRMA reverbs (NRev, KipRev), which
  6. were based on the Chowning/Moorer/Schroeder
  7. reverberators using networks of simple allpass
  8. and comb delay filters. This class implements
  9. two series allpass units and two parallel comb
  10. filters.
  11. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  12. */
  13. /***************************************************/
  14. #include "PRCRev.h"
  15. #include <cmath>
  16. namespace stk {
  17. PRCRev :: PRCRev( StkFloat T60 )
  18. {
  19. if ( T60 <= 0.0 ) {
  20. oStream_ << "PRCRev::PRCRev: argument (" << T60 << ") must be positive!";
  21. handleError( StkError::FUNCTION_ARGUMENT );
  22. }
  23. lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output
  24. // Delay lengths for 44100 Hz sample rate.
  25. int lengths[4]= {341, 613, 1557, 2137};
  26. double scaler = Stk::sampleRate() / 44100.0;
  27. // Scale the delay lengths if necessary.
  28. int delay, i;
  29. if ( scaler != 1.0 ) {
  30. for (i=0; i<4; i++) {
  31. delay = (int) floor(scaler * lengths[i]);
  32. if ( (delay & 1) == 0) delay++;
  33. while ( !this->isPrime(delay) ) delay += 2;
  34. lengths[i] = delay;
  35. }
  36. }
  37. for ( i=0; i<2; i++ ) {
  38. allpassDelays_[i].setMaximumDelay( lengths[i] );
  39. allpassDelays_[i].setDelay( lengths[i] );
  40. combDelays_[i].setMaximumDelay( lengths[i+2] );
  41. combDelays_[i].setDelay( lengths[i+2] );
  42. }
  43. this->setT60( T60 );
  44. allpassCoefficient_ = 0.7;
  45. effectMix_ = 0.5;
  46. this->clear();
  47. }
  48. void PRCRev :: clear( void )
  49. {
  50. allpassDelays_[0].clear();
  51. allpassDelays_[1].clear();
  52. combDelays_[0].clear();
  53. combDelays_[1].clear();
  54. lastFrame_[0] = 0.0;
  55. lastFrame_[1] = 0.0;
  56. }
  57. void PRCRev :: setT60( StkFloat T60 )
  58. {
  59. if ( T60 <= 0.0 ) {
  60. oStream_ << "PRCRev::setT60: argument (" << T60 << ") must be positive!";
  61. handleError( StkError::WARNING ); return;
  62. }
  63. combCoefficient_[0] = pow(10.0, (-3.0 * combDelays_[0].getDelay() / (T60 * Stk::sampleRate())));
  64. combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate())));
  65. }
  66. StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel )
  67. {
  68. #if defined(_STK_DEBUG_)
  69. if ( channel >= frames.channels() - 1 ) {
  70. oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
  71. handleError( StkError::FUNCTION_ARGUMENT );
  72. }
  73. #endif
  74. StkFloat *samples = &frames[channel];
  75. unsigned int hop = frames.channels();
  76. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
  77. *samples = tick( *samples );
  78. *(samples+1) = lastFrame_[1];
  79. }
  80. return frames;
  81. }
  82. StkFrames& PRCRev :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
  83. {
  84. #if defined(_STK_DEBUG_)
  85. if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
  86. oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!";
  87. handleError( StkError::FUNCTION_ARGUMENT );
  88. }
  89. #endif
  90. StkFloat *iSamples = &iFrames[iChannel];
  91. StkFloat *oSamples = &oFrames[oChannel];
  92. unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
  93. for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
  94. *oSamples = tick( *iSamples );
  95. *(oSamples+1) = lastFrame_[1];
  96. }
  97. return iFrames;
  98. }
  99. } // stk namespace