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