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.

129 lines
3.4KB

  1. #ifndef STK_RHODEY_H
  2. #define STK_RHODEY_H
  3. #include "FM.h"
  4. namespace stk {
  5. /***************************************************/
  6. /*! \class Rhodey
  7. \brief STK Fender Rhodes electric piano FM
  8. synthesis instrument.
  9. This class implements two simple FM Pairs
  10. summed together, also referred to as algorithm
  11. 5 of the TX81Z.
  12. \code
  13. Algorithm 5 is : 4->3--\
  14. + --> Out
  15. 2->1--/
  16. \endcode
  17. Control Change Numbers:
  18. - Modulator Index One = 2
  19. - Crossfade of Outputs = 4
  20. - LFO Speed = 11
  21. - LFO Depth = 1
  22. - ADSR 2 & 4 Target = 128
  23. The basic Chowning/Stanford FM patent expired
  24. in 1995, but there exist follow-on patents,
  25. mostly assigned to Yamaha. If you are of the
  26. type who should worry about this (making
  27. money) worry away.
  28. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  29. */
  30. /***************************************************/
  31. class Rhodey : public FM
  32. {
  33. public:
  34. //! Class constructor.
  35. /*!
  36. An StkError will be thrown if the rawwave path is incorrectly set.
  37. */
  38. Rhodey( void );
  39. //! Class destructor.
  40. ~Rhodey( void );
  41. //! Set instrument parameters for a particular frequency.
  42. void setFrequency( StkFloat frequency );
  43. //! Start a note with the given frequency and amplitude.
  44. void noteOn( StkFloat frequency, StkFloat amplitude );
  45. //! Compute and return one output sample.
  46. StkFloat tick( unsigned int channel = 0 );
  47. //! Fill a channel of the StkFrames object with computed outputs.
  48. /*!
  49. The \c channel argument must be less than the number of
  50. channels in the StkFrames argument (the first channel is specified
  51. by 0). However, range checking is only performed if _STK_DEBUG_
  52. is defined during compilation, in which case an out-of-range value
  53. will trigger an StkError exception.
  54. */
  55. StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
  56. protected:
  57. };
  58. inline StkFloat Rhodey :: tick( unsigned int )
  59. {
  60. StkFloat temp, temp2;
  61. temp = gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
  62. temp = temp * control1_;
  63. waves_[0]->addPhaseOffset( temp );
  64. waves_[3]->addPhaseOffset( twozero_.lastOut() );
  65. temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
  66. twozero_.tick(temp);
  67. waves_[2]->addPhaseOffset( temp );
  68. temp = ( 1.0 - (control2_ * 0.5)) * gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
  69. temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
  70. // Calculate amplitude modulation and apply it to output.
  71. temp2 = vibrato_.tick() * modDepth_;
  72. temp = temp * (1.0 + temp2);
  73. lastFrame_[0] = temp * 0.5;
  74. return lastFrame_[0];
  75. }
  76. inline StkFrames& Rhodey :: tick( StkFrames& frames, unsigned int channel )
  77. {
  78. unsigned int nChannels = lastFrame_.channels();
  79. #if defined(_STK_DEBUG_)
  80. if ( channel > frames.channels() - nChannels ) {
  81. oStream_ << "Rhodey::tick(): channel and StkFrames arguments are incompatible!";
  82. handleError( StkError::FUNCTION_ARGUMENT );
  83. }
  84. #endif
  85. StkFloat *samples = &frames[channel];
  86. unsigned int j, hop = frames.channels() - nChannels;
  87. if ( nChannels == 1 ) {
  88. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
  89. *samples++ = tick();
  90. }
  91. else {
  92. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
  93. *samples++ = tick();
  94. for ( j=1; j<nChannels; j++ )
  95. *samples++ = lastFrame_[j];
  96. }
  97. }
  98. return frames;
  99. }
  100. } // stk namespace
  101. #endif