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.

139 lines
3.7KB

  1. /***************************************************/
  2. /*! \class Clarinet
  3. \brief STK clarinet physical model class.
  4. This class implements a simple clarinet
  5. physical model, as discussed by Smith (1986),
  6. McIntyre, Schumacher, Woodhouse (1983), and
  7. others.
  8. This is a digital waveguide model, making its
  9. use possibly subject to patents held by Stanford
  10. University, Yamaha, and others.
  11. Control Change Numbers:
  12. - Reed Stiffness = 2
  13. - Noise Gain = 4
  14. - Vibrato Frequency = 11
  15. - Vibrato Gain = 1
  16. - Breath Pressure = 128
  17. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  18. */
  19. /***************************************************/
  20. #include "Clarinet.h"
  21. #include "SKINImsg.h"
  22. namespace stk {
  23. Clarinet :: Clarinet( StkFloat lowestFrequency )
  24. {
  25. if ( lowestFrequency <= 0.0 ) {
  26. oStream_ << "Clarinet::Clarinet: argument is less than or equal to zero!";
  27. handleError( StkError::FUNCTION_ARGUMENT );
  28. }
  29. unsigned long nDelays = (unsigned long) ( 0.5 * Stk::sampleRate() / lowestFrequency );
  30. delayLine_.setMaximumDelay( nDelays + 1 );
  31. reedTable_.setOffset( 0.7 );
  32. reedTable_.setSlope( -0.3 );
  33. vibrato_.setFrequency( 5.735 );
  34. outputGain_ = 1.0;
  35. noiseGain_ = 0.2;
  36. vibratoGain_ = 0.1;
  37. this->setFrequency( 220.0 );
  38. this->clear();
  39. }
  40. Clarinet :: ~Clarinet( void )
  41. {
  42. }
  43. void Clarinet :: clear( void )
  44. {
  45. delayLine_.clear();
  46. filter_.tick( 0.0 );
  47. }
  48. void Clarinet :: setFrequency( StkFloat frequency )
  49. {
  50. #if defined(_STK_DEBUG_)
  51. if ( frequency <= 0.0 ) {
  52. oStream_ << "Clarinet::setFrequency: argument is less than or equal to zero!";
  53. handleError( StkError::WARNING ); return;
  54. }
  55. #endif
  56. // Account for filter delay and one sample "lastOut" delay.
  57. StkFloat delay = ( Stk::sampleRate() / frequency ) * 0.5 - filter_.phaseDelay( frequency ) - 1.0;
  58. delayLine_.setDelay( delay );
  59. }
  60. void Clarinet :: startBlowing( StkFloat amplitude, StkFloat rate )
  61. {
  62. if ( amplitude <= 0.0 || rate <= 0.0 ) {
  63. oStream_ << "Clarinet::startBlowing: one or more arguments is less than or equal to zero!";
  64. handleError( StkError::WARNING ); return;
  65. }
  66. envelope_.setRate( rate );
  67. envelope_.setTarget( amplitude );
  68. }
  69. void Clarinet :: stopBlowing( StkFloat rate )
  70. {
  71. if ( rate <= 0.0 ) {
  72. oStream_ << "Clarinet::stopBlowing: argument is less than or equal to zero!";
  73. handleError( StkError::WARNING ); return;
  74. }
  75. envelope_.setRate( rate );
  76. envelope_.setTarget( 0.0 );
  77. }
  78. void Clarinet :: noteOn( StkFloat frequency, StkFloat amplitude )
  79. {
  80. this->setFrequency( frequency );
  81. this->startBlowing( 0.55 + (amplitude * 0.30), amplitude * 0.005 );
  82. outputGain_ = amplitude + 0.001;
  83. }
  84. void Clarinet :: noteOff( StkFloat amplitude )
  85. {
  86. this->stopBlowing( amplitude * 0.01 );
  87. }
  88. void Clarinet :: controlChange( int number, StkFloat value )
  89. {
  90. #if defined(_STK_DEBUG_)
  91. if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
  92. oStream_ << "Clarinet::controlChange: value (" << value << ") is out of range!";
  93. handleError( StkError::WARNING ); return;
  94. }
  95. #endif
  96. StkFloat normalizedValue = value * ONE_OVER_128;
  97. if ( number == __SK_ReedStiffness_ ) // 2
  98. reedTable_.setSlope( -0.44 + ( 0.26 * normalizedValue ) );
  99. else if ( number == __SK_NoiseLevel_ ) // 4
  100. noiseGain_ = ( normalizedValue * 0.4 );
  101. else if ( number == __SK_ModFrequency_ ) // 11
  102. vibrato_.setFrequency( normalizedValue * 12.0 );
  103. else if ( number == __SK_ModWheel_ ) // 1
  104. vibratoGain_ = ( normalizedValue * 0.5 );
  105. else if ( number == __SK_AfterTouch_Cont_ ) // 128
  106. envelope_.setValue( normalizedValue );
  107. #if defined(_STK_DEBUG_)
  108. else {
  109. oStream_ << "Clarinet::controlChange: undefined control number (" << number << ")!";
  110. handleError( StkError::WARNING );
  111. }
  112. #endif
  113. }
  114. } // stk namespace