f@5
|
1 /*
|
f@5
|
2
|
f@5
|
3 Copyright (C) 2016 Queen Mary University of London
|
f@5
|
4 Author: Fiore Martin
|
f@5
|
5
|
f@5
|
6 This file is part of Collidoscope.
|
f@5
|
7
|
f@5
|
8 Collidoscope is free software: you can redistribute it and/or modify
|
f@5
|
9 it under the terms of the GNU General Public License as published by
|
f@5
|
10 the Free Software Foundation, either version 3 of the License, or
|
f@5
|
11 (at your option) any later version.
|
f@5
|
12
|
f@5
|
13 This program is distributed in the hope that it will be useful,
|
f@5
|
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@5
|
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@5
|
16 GNU General Public License for more details.
|
f@5
|
17
|
f@5
|
18 You should have received a copy of the GNU General Public License
|
f@5
|
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@5
|
20 */
|
f@5
|
21
|
f@0
|
22 #pragma once
|
f@0
|
23
|
f@0
|
24 namespace collidoscope {
|
f@0
|
25
|
f@2
|
26
|
f@2
|
27 /*
|
f@2
|
28 * An ASR envelope with linear shape. It is modeled after the STK envelope classes.
|
f@2
|
29 * The tick() method advances the computation of the envelope one sample and returns the computed sample
|
f@2
|
30 * The class is templated for the type of the samples that each tick of the envelope produces.
|
f@2
|
31 *
|
f@2
|
32 * Client classes can set/get the current state of the envelope with the
|
f@2
|
33 * respective getter/setter methods
|
f@2
|
34 *
|
f@2
|
35 */
|
f@0
|
36 template <typename T>
|
f@0
|
37 class EnvASR
|
f@0
|
38 {
|
f@0
|
39 public:
|
f@0
|
40
|
f@3
|
41 /** Possible states of the envelope. Idle means the envelope ouputs 0 */
|
f@0
|
42 enum class State {
|
f@0
|
43 eAttack,
|
f@0
|
44 eSustain,
|
f@0
|
45 eRelease,
|
f@0
|
46 eIdle // before attack after release
|
f@0
|
47 };
|
f@0
|
48
|
f@0
|
49 EnvASR( T sustainLevel, T attackTime, T releaseTime, std::size_t sampleRate ) :
|
f@0
|
50 mSustainLevel( sustainLevel ),
|
f@0
|
51 mState( State::eIdle ),
|
f@0
|
52 mValue( 0 )
|
f@0
|
53
|
f@0
|
54 {
|
f@0
|
55 if ( attackTime <= 0 )
|
f@0
|
56 attackTime = T( 0.001 );
|
f@0
|
57
|
f@0
|
58 if ( releaseTime <= 0 )
|
f@0
|
59 releaseTime = T( 0.001 );
|
f@0
|
60
|
f@0
|
61 mAttackRate = T( 1.0 ) / (attackTime * sampleRate);
|
f@0
|
62 mReleaseRate = T( 1.0 ) / (releaseTime * sampleRate);
|
f@0
|
63 }
|
f@0
|
64
|
f@3
|
65 /** Produces one sample worth of envelope */
|
f@0
|
66 T tick()
|
f@0
|
67 {
|
f@0
|
68
|
f@0
|
69 switch ( mState )
|
f@0
|
70 {
|
f@0
|
71
|
f@0
|
72 case State::eIdle: {
|
f@0
|
73 mValue = 0;
|
f@0
|
74 };
|
f@0
|
75 break;
|
f@0
|
76
|
f@0
|
77 case State::eAttack: {
|
f@0
|
78 mValue += mAttackRate;
|
f@0
|
79 if ( mValue >= mSustainLevel ){
|
f@0
|
80 mValue = mSustainLevel;
|
f@0
|
81 mState = State::eSustain;
|
f@0
|
82 }
|
f@0
|
83 };
|
f@0
|
84 break;
|
f@0
|
85
|
f@0
|
86 case State::eRelease:
|
f@0
|
87 mValue -= mReleaseRate;
|
f@0
|
88 if ( mValue <= 0 ){
|
f@0
|
89 mValue = 0;
|
f@0
|
90 mState = State::eIdle;
|
f@0
|
91 }
|
f@0
|
92 break;
|
f@0
|
93 default:
|
f@0
|
94 break;
|
f@0
|
95 }
|
f@0
|
96
|
f@0
|
97 return mValue;
|
f@0
|
98
|
f@0
|
99 }
|
f@0
|
100
|
f@0
|
101 State getState() const
|
f@0
|
102 {
|
f@0
|
103 return mState;
|
f@0
|
104 }
|
f@0
|
105
|
f@0
|
106 void setState( State state )
|
f@0
|
107 {
|
f@0
|
108 mState = state;
|
f@0
|
109 }
|
f@0
|
110
|
f@0
|
111 private:
|
f@0
|
112 T mSustainLevel;
|
f@0
|
113 T mAttackRate;
|
f@0
|
114 T mReleaseRate;
|
f@0
|
115
|
f@0
|
116 // output
|
f@0
|
117 T mValue;
|
f@0
|
118
|
f@0
|
119 State mState;
|
f@0
|
120
|
f@0
|
121 };
|
f@0
|
122
|
f@0
|
123
|
f@2
|
124 }
|