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.

180 lines
4.6KB

  1. #ifndef STK_ADSR_H
  2. #define STK_ADSR_H
  3. #include "Generator.h"
  4. namespace stk {
  5. /***************************************************/
  6. /*! \class ADSR
  7. \brief STK ADSR envelope class.
  8. This class implements a traditional ADSR (Attack, Decay, Sustain,
  9. Release) envelope. It responds to simple keyOn and keyOff
  10. messages, keeping track of its state. The \e state = ADSR::IDLE
  11. before being triggered and after the envelope value reaches 0.0 in
  12. the ADSR::RELEASE state. All rate, target and level settings must
  13. be non-negative. All time settings are in seconds and must be
  14. positive.
  15. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  16. */
  17. /***************************************************/
  18. class ADSR : public Generator
  19. {
  20. public:
  21. //! ADSR envelope states.
  22. enum {
  23. ATTACK, /*!< Attack */
  24. DECAY, /*!< Decay */
  25. SUSTAIN, /*!< Sustain */
  26. RELEASE, /*!< Release */
  27. IDLE /*!< Before attack / after release */
  28. };
  29. //! Default constructor.
  30. ADSR( void );
  31. //! Class destructor.
  32. ~ADSR( void );
  33. //! Set target = 1, state = \e ADSR::ATTACK.
  34. void keyOn( void );
  35. //! Set target = 0, state = \e ADSR::RELEASE.
  36. void keyOff( void );
  37. //! Set the attack rate (gain / sample).
  38. void setAttackRate( StkFloat rate );
  39. //! Set the target value for the attack (default = 1.0).
  40. void setAttackTarget( StkFloat target );
  41. //! Set the decay rate (gain / sample).
  42. void setDecayRate( StkFloat rate );
  43. //! Set the sustain level.
  44. void setSustainLevel( StkFloat level );
  45. //! Set the release rate (gain / sample).
  46. void setReleaseRate( StkFloat rate );
  47. //! Set the attack rate based on a time duration (seconds).
  48. void setAttackTime( StkFloat time );
  49. //! Set the decay rate based on a time duration (seconds).
  50. void setDecayTime( StkFloat time );
  51. //! Set the release rate based on a time duration (seconds).
  52. void setReleaseTime( StkFloat time );
  53. //! Set sustain level and attack, decay, and release time durations (seconds).
  54. void setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime );
  55. //! Set a sustain target value and attack or decay from current value to target.
  56. void setTarget( StkFloat target );
  57. //! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, IDLE).
  58. int getState( void ) const { return state_; };
  59. //! Set to state = ADSR::SUSTAIN with current and target values of \e value.
  60. void setValue( StkFloat value );
  61. //! Return the last computed output value.
  62. StkFloat lastOut( void ) const { return lastFrame_[0]; };
  63. //! Compute and return one output sample.
  64. StkFloat tick( void );
  65. //! Fill a channel of the StkFrames object with computed outputs.
  66. /*!
  67. The \c channel argument must be less than the number of
  68. channels in the StkFrames argument (the first channel is specified
  69. by 0). However, range checking is only performed if _STK_DEBUG_
  70. is defined during compilation, in which case an out-of-range value
  71. will trigger an StkError exception.
  72. */
  73. StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
  74. protected:
  75. void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
  76. int state_;
  77. StkFloat value_;
  78. StkFloat target_;
  79. StkFloat attackRate_;
  80. StkFloat decayRate_;
  81. StkFloat releaseRate_;
  82. StkFloat releaseTime_;
  83. StkFloat sustainLevel_;
  84. };
  85. inline StkFloat ADSR :: tick( void )
  86. {
  87. switch ( state_ ) {
  88. case ATTACK:
  89. value_ += attackRate_;
  90. if ( value_ >= target_ ) {
  91. value_ = target_;
  92. target_ = sustainLevel_;
  93. state_ = DECAY;
  94. }
  95. lastFrame_[0] = value_;
  96. break;
  97. case DECAY:
  98. if ( value_ > sustainLevel_ ) {
  99. value_ -= decayRate_;
  100. if ( value_ <= sustainLevel_ ) {
  101. value_ = sustainLevel_;
  102. state_ = SUSTAIN;
  103. }
  104. }
  105. else {
  106. value_ += decayRate_; // attack target < sustain level
  107. if ( value_ >= sustainLevel_ ) {
  108. value_ = sustainLevel_;
  109. state_ = SUSTAIN;
  110. }
  111. }
  112. lastFrame_[0] = value_;
  113. break;
  114. case RELEASE:
  115. value_ -= releaseRate_;
  116. if ( value_ <= 0.0 ) {
  117. value_ = 0.0;
  118. state_ = IDLE;
  119. }
  120. lastFrame_[0] = value_;
  121. }
  122. return value_;
  123. }
  124. inline StkFrames& ADSR :: tick( StkFrames& frames, unsigned int channel )
  125. {
  126. #if defined(_STK_DEBUG_)
  127. if ( channel >= frames.channels() ) {
  128. oStream_ << "ADSR::tick(): channel and StkFrames arguments are incompatible!";
  129. handleError( StkError::FUNCTION_ARGUMENT );
  130. }
  131. #endif
  132. StkFloat *samples = &frames[channel];
  133. unsigned int hop = frames.channels();
  134. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
  135. *samples = ADSR::tick();
  136. return frames;
  137. }
  138. } // stk namespace
  139. #endif