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