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.

187 lines
5.7KB

  1. /***************************************************/
  2. /*! \class Mandolin
  3. \brief STK mandolin instrument model class.
  4. This class uses two "twang" models and "commuted
  5. synthesis" techniques to model a mandolin
  6. instrument.
  7. This is a digital waveguide model, making its
  8. use possibly subject to patents held by Stanford
  9. University, Yamaha, and others. Commuted
  10. Synthesis, in particular, is covered by patents,
  11. granted, pending, and/or applied-for. All are
  12. assigned to the Board of Trustees, Stanford
  13. University. For information, contact the Office
  14. of Technology Licensing, Stanford University.
  15. Control Change Numbers:
  16. - Body Size = 2
  17. - Pluck Position = 4
  18. - String Sustain = 11
  19. - String Detuning = 1
  20. - Microphone Position = 128
  21. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  22. */
  23. /***************************************************/
  24. #include "Mandolin.h"
  25. #include "SKINImsg.h"
  26. namespace stk {
  27. Mandolin :: Mandolin( StkFloat lowestFrequency )
  28. {
  29. if ( lowestFrequency <= 0.0 ) {
  30. oStream_ << "Mandolin::Mandolin: argument is less than or equal to zero!";
  31. handleError( StkError::FUNCTION_ARGUMENT );
  32. }
  33. // Concatenate the STK rawwave path to the rawwave files
  34. soundfile_[0].openFile( (Stk::rawwavePath() + "mand1.raw").c_str(), true );
  35. soundfile_[1].openFile( (Stk::rawwavePath() + "mand2.raw").c_str(), true );
  36. soundfile_[2].openFile( (Stk::rawwavePath() + "mand3.raw").c_str(), true );
  37. soundfile_[3].openFile( (Stk::rawwavePath() + "mand4.raw").c_str(), true );
  38. soundfile_[4].openFile( (Stk::rawwavePath() + "mand5.raw").c_str(), true );
  39. soundfile_[5].openFile( (Stk::rawwavePath() + "mand6.raw").c_str(), true );
  40. soundfile_[6].openFile( (Stk::rawwavePath() + "mand7.raw").c_str(), true );
  41. soundfile_[7].openFile( (Stk::rawwavePath() + "mand8.raw").c_str(), true );
  42. soundfile_[8].openFile( (Stk::rawwavePath() + "mand9.raw").c_str(), true );
  43. soundfile_[9].openFile( (Stk::rawwavePath() + "mand10.raw").c_str(), true );
  44. soundfile_[10].openFile( (Stk::rawwavePath() + "mand11.raw").c_str(), true );
  45. soundfile_[11].openFile( (Stk::rawwavePath() + "mand12.raw").c_str(), true );
  46. mic_ = 0;
  47. detuning_ = 0.995;
  48. pluckAmplitude_ = 0.5;
  49. strings_[0].setLowestFrequency( lowestFrequency );
  50. strings_[1].setLowestFrequency( lowestFrequency );
  51. this->setFrequency( 220.0 );
  52. this->setPluckPosition( 0.4 );
  53. }
  54. Mandolin :: ~Mandolin( void )
  55. {
  56. }
  57. void Mandolin :: clear( void )
  58. {
  59. strings_[0].clear();
  60. strings_[1].clear();
  61. }
  62. void Mandolin :: setPluckPosition( StkFloat position )
  63. {
  64. if ( position < 0.0 || position > 1.0 ) {
  65. oStream_ << "Mandolin::setPluckPosition: position parameter out of range!";
  66. handleError( StkError::WARNING ); return;
  67. }
  68. strings_[0].setPluckPosition( position );
  69. strings_[1].setPluckPosition( position );
  70. }
  71. void Mandolin :: setDetune( StkFloat detune )
  72. {
  73. if ( detune <= 0.0 ) {
  74. oStream_ << "Mandolin::setDeturn: parameter is less than or equal to zero!";
  75. handleError( StkError::WARNING ); return;
  76. }
  77. detuning_ = detune;
  78. strings_[1].setFrequency( frequency_ * detuning_ );
  79. }
  80. void Mandolin :: setBodySize( StkFloat size )
  81. {
  82. // Scale the commuted body response by its sample rate (22050).
  83. StkFloat rate = size * 22050.0 / Stk::sampleRate();
  84. for ( int i=0; i<12; i++ )
  85. soundfile_[i].setRate( rate );
  86. }
  87. void Mandolin :: setFrequency( StkFloat frequency )
  88. {
  89. #if defined(_STK_DEBUG_)
  90. if ( frequency <= 0.0 ) {
  91. oStream_ << "Mandolin::setFrequency: argument is less than or equal to zero!";
  92. handleError( StkError::WARNING ); return;
  93. }
  94. #endif
  95. frequency_ = frequency;
  96. strings_[0].setFrequency( frequency_ );
  97. strings_[1].setFrequency( frequency_ * detuning_ );
  98. }
  99. void Mandolin :: pluck( StkFloat amplitude )
  100. {
  101. if ( amplitude < 0.0 || amplitude > 1.0 ) {
  102. oStream_ << "Mandolin::pluck: amplitude parameter out of range!";
  103. handleError( StkError::WARNING ); return;
  104. }
  105. soundfile_[mic_].reset();
  106. pluckAmplitude_ = amplitude;
  107. //strings_[0].setLoopGain( 0.97 + pluckAmplitude_ * 0.03 );
  108. //strings_[1].setLoopGain( 0.97 + pluckAmplitude_ * 0.03 );
  109. }
  110. void Mandolin :: pluck( StkFloat amplitude, StkFloat position )
  111. {
  112. this->setPluckPosition( position );
  113. this->pluck( amplitude );
  114. }
  115. void Mandolin :: noteOn( StkFloat frequency, StkFloat amplitude )
  116. {
  117. this->setFrequency( frequency );
  118. this->pluck( amplitude );
  119. }
  120. void Mandolin :: noteOff( StkFloat amplitude )
  121. {
  122. if ( amplitude < 0.0 || amplitude > 1.0 ) {
  123. oStream_ << "Mandolin::noteOff: amplitude is out of range!";
  124. handleError( StkError::WARNING ); return;
  125. }
  126. //strings_[0].setLoopGain( 0.97 + (1 - amplitude) * 0.03 );
  127. //strings_[1].setLoopGain( 0.97 + (1 - amplitude) * 0.03 );
  128. }
  129. void Mandolin :: controlChange( int number, StkFloat value )
  130. {
  131. #if defined(_STK_DEBUG_)
  132. if ( Stk::inRange( value, 0.0, 128.0 ) == false ) {
  133. oStream_ << "Mandolin::controlChange: value (" << value << ") is out of range!";
  134. handleError( StkError::WARNING ); return;
  135. }
  136. #endif
  137. StkFloat normalizedValue = value * ONE_OVER_128;
  138. if ( number == __SK_BodySize_ ) // 2
  139. this->setBodySize( normalizedValue * 2.0 );
  140. else if ( number == __SK_PickPosition_ ) // 4
  141. this->setPluckPosition( normalizedValue );
  142. else if ( number == __SK_StringDamping_ ) { // 11
  143. strings_[0].setLoopGain( 0.97 + (normalizedValue * 0.03) );
  144. strings_[1].setLoopGain( 0.97 + (normalizedValue * 0.03) );
  145. }
  146. else if ( number == __SK_StringDetune_ ) // 1
  147. this->setDetune( 1.0 - (normalizedValue * 0.1) );
  148. else if ( number == __SK_AfterTouch_Cont_ ) // 128
  149. mic_ = (int) (normalizedValue * 11.0);
  150. #if defined(_STK_DEBUG_)
  151. else {
  152. oStream_ << "Mandolin::controlChange: undefined control number (" << number << ")!";
  153. handleError( StkError::WARNING );
  154. }
  155. #endif
  156. }
  157. } // stk namespace