ADSR.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 
00023 #include "ADSR.hxx"
00024 #include "ProcessingFactory.hxx"
00025 
00026 
00027 namespace CLAM
00028 {
00029 
00030 namespace Hidden
00031 {
00032         static const char * metadata[] = {
00033                 "key", "ADSR",
00034                 "category", "Generators",
00035                 "description", "ADSR",
00036                 0
00037         };
00038         static FactoryRegistrator<ProcessingFactory, ADSR> reg = metadata;
00039 }
00040 
00041 void ADSRConfig::DefaultInit(void)
00042 {
00043         AddAttackTime();
00044         AddDecayTime(),
00045         AddSustainLevel();
00046         AddReleaseTime();
00047         AddSampleRate();
00048 
00049         UpdateData();
00050 
00051         SetSampleRate( 8000 );
00052 }
00053 
00054 ADSR::ADSR( const ADSRConfig& cfg )
00055         : mOutput("Audio Output",this)
00056         , mAmplitude("Amplitude",this, &ADSR::UpdateAmp )
00057         , mAmpValue(0)
00058         , mLevel(0)
00059         , mDLevel(0)
00060         , mStatus(Done)
00061         , mState( "State", this )
00062 {
00063         Configure( cfg );
00064 }
00065 
00066 bool ADSR::ConcreteConfigure( const ProcessingConfig& c )
00067 {
00068         CopyAsConcreteConfig(mConfig, c);
00069 
00070         mAttackTime = mConfig.GetAttackTime();
00071         mDecayTime = mConfig.GetDecayTime();
00072         mSustainLevel = mConfig.GetSustainLevel();
00073         mReleaseTime = mConfig.GetReleaseTime();
00074         mSamplingRate = mConfig.GetSampleRate();
00075 
00076         return true;
00077 }
00078 
00079 void ADSR::HandleAttack(void)
00080 {
00081         mStatus = Attack;
00082         mLevel = 0;
00083         mDLevel = mAmpValue / ( mAttackTime * mSamplingRate );
00084 }
00085 
00086 void ADSR::HandleDecay(void)
00087 {
00088         mStatus = Decay;
00089         mDLevel = ( mSustainLevel * mAmpValue - mAmpValue ) / ( mDecayTime * mSamplingRate ) ;
00090 }
00091 
00092 void ADSR::HandleRelease(void)
00093 {
00094         mStatus = Release;
00095         mDLevel = - mLevel / ( mReleaseTime * mSamplingRate );
00096 }
00097 
00098 bool ADSR::Do( Audio& out)
00099 {
00100 /*** this is the "clean" version:
00101 
00102         TData* ptr = out.GetBuffer().GetPtr();
00103 
00104         for ( int i = 0; i < out.GetSize() ; i++ )
00105         {
00106                 (*ptr++) = mLevel ;
00107                 mLevel += mDLevel ;
00108 
00109                 if ( ( mStatus == Attack ) && ( mLevel >= mAmpValue ) )
00110                 {
00111                         mStatus = Decay ;
00112                         HandleDecay();
00113                 }
00114                 else if ( ( mStatus == Decay ) && ( mLevel <= mSustainLevel ) )
00115                 {
00116                         mStatus = Sustain ;
00117                         mDLevel = 0 ;
00118                 }
00119                 else if ( ( mStatus == Release ) && ( mLevel <= 0 ) )
00120                 {
00121                         mDLevel = 0;
00122                         mLevel = 0;
00123                         mStatus = Done;
00124                 }
00125         }
00126 */
00127 
00128 /*
00129  the following does the same, but more efficient, by moving part of the conditions
00130  outside of the for loop
00131 */
00132 
00133         TData* ptr = out.GetBuffer().GetPtr();
00134         TData* endptr = ptr+out.GetSize();
00135 
00136         if (mStatus==Attack)
00137         {
00138                 while ( ptr!=endptr )
00139                 {
00140                         (*ptr++) = mLevel ;
00141                         mLevel += mDLevel ;
00142 
00143                         if (mLevel >= mAmpValue)
00144                         {
00145                                 mStatus = Decay ;
00146                                 HandleDecay();
00147                                 break;
00148                         }
00149                 }
00150         }
00151         if (mStatus==Decay)
00152         {
00153                 while ( ptr!=endptr )
00154                 {
00155                         (*ptr++) = mLevel ;
00156                         mLevel += mDLevel ;
00157 
00158                         if (mLevel <= mSustainLevel )
00159                         {
00160                                 mStatus = Sustain ;
00161                                 mDLevel = 0 ;
00162                                 break;
00163                         }
00164                 }
00165         }
00166         if (mStatus==Sustain)
00167         {
00168                 while ( ptr!=endptr )
00169                 {
00170                         (*ptr++) = mLevel ;
00171                 }
00172         }
00173         if (mStatus==Release)
00174         {
00175                 while ( ptr!=endptr )
00176                 {
00177                         (*ptr++) = mLevel ;
00178                         mLevel += mDLevel ;
00179                         
00180                         if (mLevel <=0 )
00181                         {
00182                                 mDLevel = 0;
00183                                 mLevel = 0;
00184                                 mStatus = Done;
00185                                 break;
00186                         }
00187                 }
00188         }
00189         if (mStatus==Done)
00190         {
00191                 while ( ptr!=endptr )
00192                 {
00193                         (*ptr++) = 0 ;
00194                 }
00195         }
00196 
00197         UpdateState();
00198 
00199         return true;
00200         
00201 }
00202 
00203 bool ADSR::Do()
00204 {       
00205         bool res = false;
00206         res = Do(mOutput.GetAudio());
00207         mOutput.Produce();
00208         return res;
00209 
00210 
00211 }
00212 
00213 }
00214 
Generated by  doxygen 1.6.3