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.

128 lines
3.5KB

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