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.

123 lines
3.0KB

  1. /***************************************************/
  2. /*! \class BlowBotl
  3. \brief STK blown bottle instrument class.
  4. This class implements a helmholtz resonator
  5. (biquad filter) with a polynomial jet
  6. excitation (a la Cook).
  7. Control Change Numbers:
  8. - Noise Gain = 4
  9. - Vibrato Frequency = 11
  10. - Vibrato Gain = 1
  11. - Volume = 128
  12. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  13. */
  14. /***************************************************/
  15. #include "BlowBotl.h"
  16. #include "SKINImsg.h"
  17. namespace stk {
  18. #define __BOTTLE_RADIUS_ 0.999
  19. BlowBotl :: BlowBotl( void )
  20. {
  21. dcBlock_.setBlockZero();
  22. vibrato_.setFrequency( 5.925 );
  23. vibratoGain_ = 0.0;
  24. resonator_.setResonance( 500.0, __BOTTLE_RADIUS_, true );
  25. adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 );
  26. noiseGain_ = 20.0;
  27. maxPressure_ = 0.0;
  28. }
  29. BlowBotl :: ~BlowBotl( void )
  30. {
  31. }
  32. void BlowBotl :: clear( void )
  33. {
  34. resonator_.clear();
  35. }
  36. void BlowBotl :: setFrequency( StkFloat frequency )
  37. {
  38. #if defined(_STK_DEBUG_)
  39. if ( frequency <= 0.0 ) {
  40. oStream_ << "BlowBotl::setFrequency: argument is less than or equal to zero!";
  41. handleError( StkError::WARNING ); return;
  42. }
  43. #endif
  44. resonator_.setResonance( frequency, __BOTTLE_RADIUS_, true );
  45. }
  46. void BlowBotl :: startBlowing( StkFloat amplitude, StkFloat rate )
  47. {
  48. if ( amplitude <= 0.0 || rate <= 0.0 ) {
  49. oStream_ << "BlowBotl::startBowing: one or more arguments is less than or equal to zero!";
  50. handleError( StkError::WARNING ); return;
  51. }
  52. adsr_.setAttackRate( rate );
  53. maxPressure_ = amplitude;
  54. adsr_.keyOn();
  55. }
  56. void BlowBotl :: stopBlowing( StkFloat rate )
  57. {
  58. if ( rate <= 0.0 ) {
  59. oStream_ << "BlowBotl::stopBowing: argument is less than or equal to zero!";
  60. handleError( StkError::WARNING ); return;
  61. }
  62. adsr_.setReleaseRate( rate );
  63. adsr_.keyOff();
  64. }
  65. void BlowBotl :: noteOn( StkFloat frequency, StkFloat amplitude )
  66. {
  67. this->setFrequency( frequency );
  68. startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02);
  69. outputGain_ = amplitude + 0.001;
  70. }
  71. void BlowBotl :: noteOff( StkFloat amplitude )
  72. {
  73. this->stopBlowing( amplitude * 0.02 );
  74. }
  75. void BlowBotl :: controlChange( int number, StkFloat value )
  76. {
  77. #if defined(_STK_DEBUG_)
  78. if ( value < 0 || ( number != 101 && value > 128.0 ) ) {
  79. oStream_ << "BlowBotl::controlChange: value (" << value << ") is out of range!";
  80. handleError( StkError::WARNING ); return;
  81. }
  82. #endif
  83. StkFloat normalizedValue = value * ONE_OVER_128;
  84. if (number == __SK_NoiseLevel_) // 4
  85. noiseGain_ = normalizedValue * 30.0;
  86. else if (number == __SK_ModFrequency_) // 11
  87. vibrato_.setFrequency( normalizedValue * 12.0 );
  88. else if (number == __SK_ModWheel_) // 1
  89. vibratoGain_ = normalizedValue * 0.4;
  90. else if (number == __SK_AfterTouch_Cont_) // 128
  91. adsr_.setTarget( normalizedValue );
  92. #if defined(_STK_DEBUG_)
  93. else {
  94. oStream_ << "BlowBotl::controlChange: undefined control number (" << number << ")!";
  95. handleError( StkError::WARNING );
  96. }
  97. #endif
  98. }
  99. } // stk namespace