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