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.

182 lines
5.0KB

  1. /***************************************************/
  2. /*! \class StifKarp
  3. \brief STK plucked stiff string instrument.
  4. This class implements a simple plucked string
  5. algorithm (Karplus Strong) with enhancements
  6. (Jaffe-Smith, Smith, and others), including
  7. string stiffness and pluck position controls.
  8. The stiffness is modeled with allpass filters.
  9. This is a digital waveguide model, making its
  10. use possibly subject to patents held by
  11. Stanford University, Yamaha, and others.
  12. Control Change Numbers:
  13. - Pickup Position = 4
  14. - String Sustain = 11
  15. - String Stretch = 1
  16. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  17. */
  18. /***************************************************/
  19. #include "StifKarp.h"
  20. #include "SKINImsg.h"
  21. #include <cmath>
  22. namespace stk {
  23. StifKarp :: StifKarp( StkFloat lowestFrequency )
  24. {
  25. if ( lowestFrequency <= 0.0 ) {
  26. oStream_ << "StifKarp::StifKarp: argument is less than or equal to zero!";
  27. handleError( StkError::FUNCTION_ARGUMENT );
  28. }
  29. unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / lowestFrequency );
  30. delayLine_.setMaximumDelay( nDelays + 1 );
  31. combDelay_.setMaximumDelay( nDelays + 1 );
  32. pluckAmplitude_ = 0.3;
  33. pickupPosition_ = 0.4;
  34. stretching_ = 0.9999;
  35. baseLoopGain_ = 0.995;
  36. loopGain_ = 0.999;
  37. this->clear();
  38. this->setFrequency( 220.0 );
  39. }
  40. StifKarp :: ~StifKarp( void )
  41. {
  42. }
  43. void StifKarp :: clear( void )
  44. {
  45. delayLine_.clear();
  46. combDelay_.clear();
  47. filter_.clear();
  48. }
  49. void StifKarp :: setFrequency( StkFloat frequency )
  50. {
  51. #if defined(_STK_DEBUG_)
  52. if ( frequency <= 0.0 ) {
  53. oStream_ << "StifKarp::setFrequency: parameter is less than or equal to zero!";
  54. handleError( StkError::WARNING ); return;
  55. }
  56. #endif
  57. lastFrequency_ = frequency;
  58. lastLength_ = Stk::sampleRate() / lastFrequency_;
  59. StkFloat delay = lastLength_ - 0.5;
  60. delayLine_.setDelay( delay );
  61. loopGain_ = baseLoopGain_ + (frequency * 0.000005);
  62. if (loopGain_ >= 1.0) loopGain_ = 0.99999;
  63. setStretch(stretching_);
  64. combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );
  65. }
  66. void StifKarp :: setStretch( StkFloat stretch )
  67. {
  68. stretching_ = stretch;
  69. StkFloat coefficient;
  70. StkFloat freq = lastFrequency_ * 2.0;
  71. StkFloat dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25;
  72. StkFloat temp = 0.5 + (stretch * 0.5);
  73. if ( temp > 0.9999 ) temp = 0.9999;
  74. for ( int i=0; i<4; i++ ) {
  75. coefficient = temp * temp;
  76. biquad_[i].setA2( coefficient );
  77. biquad_[i].setB0( coefficient );
  78. biquad_[i].setB2( 1.0 );
  79. coefficient = -2.0 * temp * cos(TWO_PI * freq / Stk::sampleRate());
  80. biquad_[i].setA1( coefficient );
  81. biquad_[i].setB1( coefficient );
  82. freq += dFreq;
  83. }
  84. }
  85. void StifKarp :: setPickupPosition( StkFloat position ) {
  86. if ( position < 0.0 || position > 1.0 ) {
  87. oStream_ << "StifKarp::setPickupPosition: parameter is out of range!";
  88. handleError( StkError::WARNING ); return;
  89. }
  90. // Set the pick position, which puts zeroes at position * length.
  91. pickupPosition_ = position;
  92. combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );
  93. }
  94. void StifKarp :: setBaseLoopGain( StkFloat aGain )
  95. {
  96. baseLoopGain_ = aGain;
  97. loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005);
  98. if ( loopGain_ > 0.99999 ) loopGain_ = (StkFloat) 0.99999;
  99. }
  100. void StifKarp :: pluck( StkFloat amplitude )
  101. {
  102. if ( amplitude < 0.0 || amplitude > 1.0 ) {
  103. oStream_ << "StifKarp::pluck: amplitude is out of range!";
  104. handleError( StkError::WARNING ); return;
  105. }
  106. pluckAmplitude_ = amplitude;
  107. for ( unsigned long i=0; i<length_; i++ ) {
  108. // Fill delay with noise additively with current contents.
  109. delayLine_.tick( (delayLine_.lastOut() * 0.6) + 0.4 * noise_.tick() * pluckAmplitude_ );
  110. //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
  111. }
  112. }
  113. void StifKarp :: noteOn( StkFloat frequency, StkFloat amplitude )
  114. {
  115. this->setFrequency( frequency );
  116. this->pluck( amplitude );
  117. }
  118. void StifKarp :: noteOff( StkFloat amplitude )
  119. {
  120. if ( amplitude < 0.0 || amplitude > 1.0 ) {
  121. oStream_ << "StifKarp::noteOff: amplitude is out of range!";
  122. handleError( StkError::WARNING ); return;
  123. }
  124. loopGain_ = (1.0 - amplitude) * 0.5;
  125. }
  126. void StifKarp :: controlChange( int number, StkFloat value )
  127. {
  128. #if defined(_STK_DEBUG_)
  129. if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
  130. oStream_ << "Clarinet::controlChange: value (" << value << ") is out of range!";
  131. handleError( StkError::WARNING ); return;
  132. }
  133. #endif
  134. StkFloat normalizedValue = value * ONE_OVER_128;
  135. if (number == __SK_PickPosition_) // 4
  136. this->setPickupPosition( normalizedValue );
  137. else if (number == __SK_StringDamping_) // 11
  138. this->setBaseLoopGain( 0.97 + (normalizedValue * 0.03) );
  139. else if (number == __SK_StringDetune_) // 1
  140. this->setStretch( 0.9 + (0.1 * (1.0 - normalizedValue)) );
  141. #if defined(_STK_DEBUG_)
  142. else {
  143. oStream_ << "StifKarp::controlChange: undefined control number (" << number << ")!";
  144. handleError( StkError::WARNING );
  145. }
  146. #endif
  147. }
  148. } // stk namespace