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.

365 lines
9.5KB

  1. /***************************************************/
  2. /*! \class BandedWG
  3. \brief Banded waveguide modeling class.
  4. This class uses banded waveguide techniques to
  5. model a variety of sounds, including bowed
  6. bars, glasses, and bowls. For more
  7. information, see Essl, G. and Cook, P. "Banded
  8. Waveguides: Towards Physical Modelling of Bar
  9. Percussion Instruments", Proceedings of the
  10. 1999 International Computer Music Conference.
  11. Control Change Numbers:
  12. - Bow Pressure = 2
  13. - Bow Motion = 4
  14. - Strike Position = 8 (not implemented)
  15. - Vibrato Frequency = 11
  16. - Gain = 1
  17. - Bow Velocity = 128
  18. - Set Striking = 64
  19. - Instrument Presets = 16
  20. - Uniform Bar = 0
  21. - Tuned Bar = 1
  22. - Glass Harmonica = 2
  23. - Tibetan Bowl = 3
  24. by Georg Essl, 1999 - 2004.
  25. Modified for STK 4.0 by Gary Scavone.
  26. */
  27. /***************************************************/
  28. #include "BandedWG.h"
  29. #include "SKINImsg.h"
  30. #include <cmath>
  31. namespace stk {
  32. BandedWG :: BandedWG( void )
  33. {
  34. doPluck_ = true;
  35. bowTable_.setSlope( 3.0 );
  36. adsr_.setAllTimes( 0.02, 0.005, 0.9, 0.01 );
  37. frequency_ = 220.0;
  38. this->setPreset(0);
  39. bowPosition_ = 0;
  40. baseGain_ = 0.999;
  41. integrationConstant_ = 0.0;
  42. trackVelocity_ = false;
  43. bowVelocity_ = 0.0;
  44. bowTarget_ = 0.0;
  45. strikeAmp_ = 0.0;
  46. }
  47. BandedWG :: ~BandedWG( void )
  48. {
  49. }
  50. void BandedWG :: clear( void )
  51. {
  52. for ( int i=0; i<nModes_; i++ ) {
  53. delay_[i].clear();
  54. bandpass_[i].clear();
  55. }
  56. }
  57. void BandedWG :: setPreset( int preset )
  58. {
  59. int i;
  60. switch ( preset ) {
  61. case 1: // Tuned Bar
  62. presetModes_ = 4;
  63. modes_[0] = (StkFloat) 1.0;
  64. modes_[1] = (StkFloat) 4.0198391420;
  65. modes_[2] = (StkFloat) 10.7184986595;
  66. modes_[3] = (StkFloat) 18.0697050938;
  67. for (i=0; i<presetModes_; i++) {
  68. basegains_[i] = (StkFloat) pow(0.999,(double) i+1);
  69. excitation_[i] = 1.0;
  70. }
  71. break;
  72. case 2: // Glass Harmonica
  73. presetModes_ = 5;
  74. modes_[0] = (StkFloat) 1.0;
  75. modes_[1] = (StkFloat) 2.32;
  76. modes_[2] = (StkFloat) 4.25;
  77. modes_[3] = (StkFloat) 6.63;
  78. modes_[4] = (StkFloat) 9.38;
  79. // modes_[5] = (StkFloat) 12.22;
  80. for (i=0; i<presetModes_; i++) {
  81. basegains_[i] = (StkFloat) pow(0.999,(double) i+1);
  82. excitation_[i] = 1.0;
  83. }
  84. /*
  85. baseGain_ = (StkFloat) 0.99999;
  86. for (i=0; i<presetModes_; i++)
  87. gains_[i]= (StkFloat) pow(baseGain_, delay_[i].getDelay()+i);
  88. */
  89. break;
  90. case 3: // Tibetan Prayer Bowl (ICMC'02)
  91. presetModes_ = 12;
  92. modes_[0]=0.996108344;
  93. basegains_[0]=0.999925960128219;
  94. excitation_[0]=11.900357/10.0;
  95. modes_[1]=1.0038916562;
  96. basegains_[1]=0.999925960128219;
  97. excitation_[1]=11.900357/10.;
  98. modes_[2]=2.979178;
  99. basegains_[2]=0.999982774366897;
  100. excitation_[2]=10.914886/10.;
  101. modes_[3]=2.99329767;
  102. basegains_[3]=0.999982774366897;
  103. excitation_[3]=10.914886/10.;
  104. modes_[4]=5.704452;
  105. basegains_[4]=1.0; //0.999999999999999999987356406352;
  106. excitation_[4]=42.995041/10.;
  107. modes_[5]=5.704452;
  108. basegains_[5]=1.0; //0.999999999999999999987356406352;
  109. excitation_[5]=42.995041/10.;
  110. modes_[6]=8.9982;
  111. basegains_[6]=1.0; //0.999999999999999999996995497558225;
  112. excitation_[6]=40.063034/10.;
  113. modes_[7]=9.01549726;
  114. basegains_[7]=1.0; //0.999999999999999999996995497558225;
  115. excitation_[7]=40.063034/10.;
  116. modes_[8]=12.83303;
  117. basegains_[8]=0.999965497558225;
  118. excitation_[8]=7.063034/10.;
  119. modes_[9]=12.807382;
  120. basegains_[9]=0.999965497558225;
  121. excitation_[9]=7.063034/10.;
  122. modes_[10]=17.2808219;
  123. basegains_[10]=0.9999999999999999999965497558225;
  124. excitation_[10]=57.063034/10.;
  125. modes_[11]=21.97602739726;
  126. basegains_[11]=0.999999999999999965497558225;
  127. excitation_[11]=57.063034/10.;
  128. break;
  129. default: // Uniform Bar
  130. presetModes_ = 4;
  131. modes_[0] = (StkFloat) 1.0;
  132. modes_[1] = (StkFloat) 2.756;
  133. modes_[2] = (StkFloat) 5.404;
  134. modes_[3] = (StkFloat) 8.933;
  135. for (i=0; i<presetModes_; i++) {
  136. basegains_[i] = (StkFloat) pow(0.9,(double) i+1);
  137. excitation_[i] = 1.0;
  138. }
  139. break;
  140. }
  141. nModes_ = presetModes_;
  142. setFrequency( frequency_ );
  143. }
  144. void BandedWG :: setFrequency( StkFloat frequency )
  145. {
  146. #if defined(_STK_DEBUG_)
  147. if ( frequency <= 0.0 ) {
  148. oStream_ << "BandedWG::setFrequency: parameter is less than or equal to zero!";
  149. handleError( StkError::WARNING ); return;
  150. }
  151. #endif
  152. if (frequency > 1568.0) frequency = 1568.0;
  153. StkFloat radius;
  154. StkFloat base = Stk::sampleRate() / frequency;
  155. StkFloat length;
  156. for (int i=0; i<presetModes_; i++) {
  157. // Calculate the delay line lengths for each mode.
  158. length = (int)(base / modes_[i]);
  159. if ( length > 2.0) {
  160. delay_[i].setDelay( length );
  161. gains_[i]=basegains_[i];
  162. // gains_[i]=(StkFloat) pow(basegains_[i], 1/((StkFloat)delay_[i].getDelay()));
  163. // std::cerr << gains_[i];
  164. }
  165. else {
  166. nModes_ = i;
  167. break;
  168. }
  169. // std::cerr << std::endl;
  170. // Set the bandpass filter resonances
  171. radius = 1.0 - PI * 32 / Stk::sampleRate(); //frequency_ * modes_[i] / Stk::sampleRate()/32;
  172. if ( radius < 0.0 ) radius = 0.0;
  173. bandpass_[i].setResonance(frequency * modes_[i], radius, true);
  174. delay_[i].clear();
  175. bandpass_[i].clear();
  176. }
  177. //int olen = (int)(delay_[0].getDelay());
  178. //strikePosition_ = (int)(strikePosition_*(length/modes_[0])/olen);
  179. }
  180. void BandedWG :: setStrikePosition( StkFloat position )
  181. {
  182. strikePosition_ = (int)(delay_[0].getDelay() * position / 2.0);
  183. }
  184. void BandedWG :: startBowing( StkFloat amplitude, StkFloat rate )
  185. {
  186. adsr_.setAttackRate(rate);
  187. adsr_.keyOn();
  188. maxVelocity_ = 0.03 + (0.1 * amplitude);
  189. }
  190. void BandedWG :: stopBowing( StkFloat rate )
  191. {
  192. adsr_.setReleaseRate(rate);
  193. adsr_.keyOff();
  194. }
  195. void BandedWG :: pluck( StkFloat amplitude )
  196. {
  197. int j;
  198. StkFloat min_len = delay_[nModes_-1].getDelay();
  199. for (int i=0; i<nModes_; i++)
  200. for(j=0; j<(int)(delay_[i].getDelay()/min_len); j++)
  201. delay_[i].tick( excitation_[i]*amplitude / nModes_ );
  202. // strikeAmp_ += amplitude;
  203. }
  204. void BandedWG :: noteOn( StkFloat frequency, StkFloat amplitude )
  205. {
  206. this->setFrequency( frequency );
  207. if ( doPluck_ )
  208. this->pluck( amplitude );
  209. else
  210. this->startBowing( amplitude, amplitude * 0.001 );
  211. }
  212. void BandedWG :: noteOff( StkFloat amplitude )
  213. {
  214. if ( !doPluck_ )
  215. this->stopBowing( (1.0 - amplitude) * 0.005 );
  216. }
  217. StkFloat BandedWG :: tick( unsigned int )
  218. {
  219. int k;
  220. StkFloat input = 0.0;
  221. if ( doPluck_ ) {
  222. input = 0.0;
  223. // input = strikeAmp_/nModes_;
  224. // strikeAmp_ = 0.0;
  225. }
  226. else {
  227. if ( integrationConstant_ == 0.0 )
  228. velocityInput_ = 0.0;
  229. else
  230. velocityInput_ = integrationConstant_ * velocityInput_;
  231. for ( k=0; k<nModes_; k++ )
  232. velocityInput_ += baseGain_ * delay_[k].lastOut();
  233. if ( trackVelocity_ ) {
  234. bowVelocity_ *= 0.9995;
  235. bowVelocity_ += bowTarget_;
  236. bowTarget_ *= 0.995;
  237. }
  238. else
  239. bowVelocity_ = adsr_.tick() * maxVelocity_;
  240. input = bowVelocity_ - velocityInput_;
  241. input = input * bowTable_.tick(input);
  242. input = input/(StkFloat)nModes_;
  243. }
  244. StkFloat data = 0.0;
  245. for ( k=0; k<nModes_; k++ ) {
  246. bandpass_[k].tick(input + gains_[k] * delay_[k].lastOut());
  247. delay_[k].tick(bandpass_[k].lastOut());
  248. data += bandpass_[k].lastOut();
  249. }
  250. //lastFrame_[0] = data * nModes_;
  251. lastFrame_[0] = data * 4;
  252. return lastFrame_[0];
  253. }
  254. void BandedWG :: controlChange( int number, StkFloat value )
  255. {
  256. #if defined(_STK_DEBUG_)
  257. if ( value < 0 || ( number != 101 && value > 128.0 ) ) {
  258. oStream_ << "BandedWG::controlChange: value (" << value << ") is out of range!";
  259. handleError( StkError::WARNING ); return;
  260. }
  261. #endif
  262. StkFloat normalizedValue = value * ONE_OVER_128;
  263. if (number == __SK_BowPressure_) { // 2
  264. if ( normalizedValue == 0.0 )
  265. doPluck_ = true;
  266. else {
  267. doPluck_ = false;
  268. bowTable_.setSlope( 10.0 - (9.0 * normalizedValue));
  269. }
  270. }
  271. else if (number == 4) { // 4
  272. if ( !trackVelocity_ ) trackVelocity_ = true;
  273. bowTarget_ += 0.005 * (normalizedValue - bowPosition_);
  274. bowPosition_ = normalizedValue;
  275. //adsr_.setTarget(bowPosition_);
  276. }
  277. else if (number == 8) // 8
  278. this->setStrikePosition( normalizedValue );
  279. else if (number == __SK_AfterTouch_Cont_) { // 128
  280. //bowTarget_ += 0.02 * (normalizedValue - bowPosition_);
  281. //bowPosition_ = normalizedValue;
  282. if ( trackVelocity_ ) trackVelocity_ = false;
  283. maxVelocity_ = 0.13 * normalizedValue;
  284. adsr_.setTarget(normalizedValue);
  285. }
  286. else if (number == __SK_ModWheel_) { // 1
  287. // baseGain_ = 0.9989999999 + (0.001 * normalizedValue );
  288. baseGain_ = 0.8999999999999999 + (0.1 * normalizedValue);
  289. // std::cerr << "Yuck!" << std::endl;
  290. for (int i=0; i<nModes_; i++)
  291. gains_[i]=(StkFloat) basegains_[i]*baseGain_;
  292. // gains_[i]=(StkFloat) pow(baseGain_, (int)((StkFloat)delay_[i].getDelay()+i));
  293. }
  294. else if (number == __SK_ModFrequency_) // 11
  295. integrationConstant_ = normalizedValue;
  296. else if (number == __SK_Sustain_) { // 64
  297. if (value < 65) doPluck_ = true;
  298. else doPluck_ = false;
  299. }
  300. else if (number == __SK_Portamento_) { // 65
  301. if (value < 65) trackVelocity_ = false;
  302. else trackVelocity_ = true;
  303. }
  304. else if (number == __SK_ProphesyRibbon_) // 16
  305. this->setPreset((int) value);
  306. #if defined(_STK_DEBUG_)
  307. else {
  308. oStream_ << "BandedWG::controlChange: undefined control number (" << number << ")!";
  309. handleError( StkError::WARNING );
  310. }
  311. #endif
  312. }
  313. } // stk namespace