CLAM-Development  1.4.0
ADSR.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 
23 #include "ADSR.hxx"
24 #include "ProcessingFactory.hxx"
25 
26 
27 namespace CLAM
28 {
29 
30 namespace Hidden
31 {
32  static const char * metadata[] = {
33  "key", "ADSR",
34  "category", "Generators",
35  "description", "ADSR",
36  0
37  };
38  static FactoryRegistrator<ProcessingFactory, ADSR> reg = metadata;
39 }
40 
42 {
43  AddAttackTime();
44  AddDecayTime(),
45  AddSustainLevel();
46  AddReleaseTime();
47  AddSampleRate();
48 
49  UpdateData();
50 
51  SetSampleRate( 8000 );
52 }
53 
54 ADSR::ADSR( const ADSRConfig& cfg )
55  : mOutput("Audio Output",this)
56  , mAmplitude("Amplitude",this, &ADSR::UpdateAmp )
57  , mAmpValue(0)
58  , mLevel(0)
59  , mDLevel(0)
60  , mStatus(Done)
61  , mState( "State", this )
62 {
63  Configure( cfg );
64 }
65 
67 {
68  CopyAsConcreteConfig(mConfig, c);
69 
70  mAttackTime = mConfig.GetAttackTime();
71  mDecayTime = mConfig.GetDecayTime();
72  mSustainLevel = mConfig.GetSustainLevel();
73  mReleaseTime = mConfig.GetReleaseTime();
74  mSamplingRate = mConfig.GetSampleRate();
75 
76  return true;
77 }
78 
80 {
81  mStatus = Attack;
82  mLevel = 0;
83  mDLevel = mAmpValue / ( mAttackTime * mSamplingRate );
84 }
85 
87 {
88  mStatus = Decay;
89  mDLevel = ( mSustainLevel * mAmpValue - mAmpValue ) / ( mDecayTime * mSamplingRate ) ;
90 }
91 
93 {
94  mStatus = Release;
95  mDLevel = - mLevel / ( mReleaseTime * mSamplingRate );
96 }
97 
98 bool ADSR::Do( Audio& out)
99 {
100 /*** this is the "clean" version:
101 
102  TData* ptr = out.GetBuffer().GetPtr();
103 
104  for ( int i = 0; i < out.GetSize() ; i++ )
105  {
106  (*ptr++) = mLevel ;
107  mLevel += mDLevel ;
108 
109  if ( ( mStatus == Attack ) && ( mLevel >= mAmpValue ) )
110  {
111  mStatus = Decay ;
112  HandleDecay();
113  }
114  else if ( ( mStatus == Decay ) && ( mLevel <= mSustainLevel ) )
115  {
116  mStatus = Sustain ;
117  mDLevel = 0 ;
118  }
119  else if ( ( mStatus == Release ) && ( mLevel <= 0 ) )
120  {
121  mDLevel = 0;
122  mLevel = 0;
123  mStatus = Done;
124  }
125  }
126 */
127 
128 /*
129  the following does the same, but more efficient, by moving part of the conditions
130  outside of the for loop
131 */
132 
133  TData* ptr = out.GetBuffer().GetPtr();
134  TData* endptr = ptr+out.GetSize();
135 
136  if (mStatus==Attack)
137  {
138  while ( ptr!=endptr )
139  {
140  (*ptr++) = mLevel ;
141  mLevel += mDLevel ;
142 
143  if (mLevel >= mAmpValue)
144  {
145  mStatus = Decay ;
146  HandleDecay();
147  break;
148  }
149  }
150  }
151  if (mStatus==Decay)
152  {
153  while ( ptr!=endptr )
154  {
155  (*ptr++) = mLevel ;
156  mLevel += mDLevel ;
157 
158  if (mLevel <= mSustainLevel )
159  {
160  mStatus = Sustain ;
161  mDLevel = 0 ;
162  break;
163  }
164  }
165  }
166  if (mStatus==Sustain)
167  {
168  while ( ptr!=endptr )
169  {
170  (*ptr++) = mLevel ;
171  }
172  }
173  if (mStatus==Release)
174  {
175  while ( ptr!=endptr )
176  {
177  (*ptr++) = mLevel ;
178  mLevel += mDLevel ;
179 
180  if (mLevel <=0 )
181  {
182  mDLevel = 0;
183  mLevel = 0;
184  mStatus = Done;
185  break;
186  }
187  }
188  }
189  if (mStatus==Done)
190  {
191  while ( ptr!=endptr )
192  {
193  (*ptr++) = 0 ;
194  }
195  }
196 
197  UpdateState();
198 
199  return true;
200 
201 }
202 
203 bool ADSR::Do()
204 {
205  bool res = false;
206  res = Do(mOutput.GetAudio());
207  mOutput.Produce();
208  return res;
209 
210 
211 }
212 
213 }
214