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.

170 lines
4.1KB

  1. /***************************************************/
  2. /*! \class Modal
  3. \brief STK resonance model abstract base class.
  4. This class contains an excitation wavetable,
  5. an envelope, an oscillator, and N resonances
  6. (non-sweeping BiQuad filters), where N is set
  7. during instantiation.
  8. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  9. */
  10. /***************************************************/
  11. #include "Modal.h"
  12. #include <cstdlib>
  13. namespace stk {
  14. Modal :: Modal( unsigned int modes )
  15. : nModes_(modes)
  16. {
  17. if ( nModes_ == 0 ) {
  18. oStream_ << "Modal: 'modes' argument to constructor is zero!";
  19. handleError( StkError::FUNCTION_ARGUMENT );
  20. }
  21. // We don't make the excitation wave here yet, because we don't know
  22. // what it's going to be.
  23. ratios_.resize( nModes_ );
  24. radii_.resize( nModes_ );
  25. filters_ = (BiQuad **) calloc( nModes_, sizeof(BiQuad *) );
  26. for (unsigned int i=0; i<nModes_; i++ ) {
  27. filters_[i] = new BiQuad;
  28. filters_[i]->setEqualGainZeroes();
  29. }
  30. // Set some default values.
  31. vibrato_.setFrequency( 6.0 );
  32. vibratoGain_ = 0.0;
  33. directGain_ = 0.0;
  34. masterGain_ = 1.0;
  35. baseFrequency_ = 440.0;
  36. this->clear();
  37. stickHardness_ = 0.5;
  38. strikePosition_ = 0.561;
  39. }
  40. Modal :: ~Modal( void )
  41. {
  42. for ( unsigned int i=0; i<nModes_; i++ ) {
  43. delete filters_[i];
  44. }
  45. free( filters_ );
  46. }
  47. void Modal :: clear( void )
  48. {
  49. onepole_.clear();
  50. for ( unsigned int i=0; i<nModes_; i++ )
  51. filters_[i]->clear();
  52. }
  53. void Modal :: setFrequency( StkFloat frequency )
  54. {
  55. #if defined(_STK_DEBUG_)
  56. if ( frequency <= 0.0 ) {
  57. oStream_ << "Modal::setFrequency: argument is less than or equal to zero!";
  58. handleError( StkError::WARNING ); return;
  59. }
  60. #endif
  61. baseFrequency_ = frequency;
  62. for ( unsigned int i=0; i<nModes_; i++ )
  63. this->setRatioAndRadius( i, ratios_[i], radii_[i] );
  64. }
  65. void Modal :: setRatioAndRadius( unsigned int modeIndex, StkFloat ratio, StkFloat radius )
  66. {
  67. if ( modeIndex >= nModes_ ) {
  68. oStream_ << "Modal::setRatioAndRadius: modeIndex parameter is greater than number of modes!";
  69. handleError( StkError::WARNING ); return;
  70. }
  71. StkFloat nyquist = Stk::sampleRate() / 2.0;
  72. StkFloat temp;
  73. if ( ratio * baseFrequency_ < nyquist ) {
  74. ratios_[modeIndex] = ratio;
  75. }
  76. else {
  77. temp = ratio;
  78. while (temp * baseFrequency_ > nyquist) temp *= 0.5;
  79. ratios_[modeIndex] = temp;
  80. #if defined(_STK_DEBUG_)
  81. oStream_ << "Modal::setRatioAndRadius: aliasing would occur here ... correcting.";
  82. handleError( StkError::DEBUG_PRINT );
  83. #endif
  84. }
  85. radii_[modeIndex] = radius;
  86. if (ratio < 0)
  87. temp = -ratio;
  88. else
  89. temp = ratio * baseFrequency_;
  90. filters_[modeIndex]->setResonance(temp, radius);
  91. }
  92. void Modal :: setModeGain( unsigned int modeIndex, StkFloat gain )
  93. {
  94. if ( modeIndex >= nModes_ ) {
  95. oStream_ << "Modal::setModeGain: modeIndex parameter is greater than number of modes!";
  96. handleError( StkError::WARNING ); return;
  97. }
  98. filters_[modeIndex]->setGain( gain );
  99. }
  100. void Modal :: strike( StkFloat amplitude )
  101. {
  102. if ( amplitude < 0.0 || amplitude > 1.0 ) {
  103. oStream_ << "Modal::strike: amplitude is out of range!";
  104. handleError( StkError::WARNING );
  105. }
  106. envelope_.setRate( 1.0 );
  107. envelope_.setTarget( amplitude );
  108. onepole_.setPole( 1.0 - amplitude );
  109. envelope_.tick();
  110. wave_->reset();
  111. StkFloat temp;
  112. for ( unsigned int i=0; i<nModes_; i++ ) {
  113. if (ratios_[i] < 0)
  114. temp = -ratios_[i];
  115. else
  116. temp = ratios_[i] * baseFrequency_;
  117. filters_[i]->setResonance(temp, radii_[i]);
  118. }
  119. }
  120. void Modal :: noteOn( StkFloat frequency, StkFloat amplitude )
  121. {
  122. this->strike( amplitude );
  123. this->setFrequency( frequency );
  124. }
  125. void Modal :: noteOff( StkFloat amplitude )
  126. {
  127. // This calls damp, but inverts the meaning of amplitude (high
  128. // amplitude means fast damping).
  129. this->damp( 1.0 - (amplitude * 0.03) );
  130. }
  131. void Modal :: damp( StkFloat amplitude )
  132. {
  133. StkFloat temp;
  134. for ( unsigned int i=0; i<nModes_; i++ ) {
  135. if ( ratios_[i] < 0 )
  136. temp = -ratios_[i];
  137. else
  138. temp = ratios_[i] * baseFrequency_;
  139. filters_[i]->setResonance( temp, radii_[i]*amplitude );
  140. }
  141. }
  142. } // stk namespace