CLAM-Development
1.1
|
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() 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 ADSRConfig cfg; 00064 00065 Configure( cfg ); 00066 } 00067 00068 ADSR::ADSR( const ADSRConfig& cfg ) 00069 : mOutput("Audio Output",this) 00070 , mAmplitude("Amplitude",this, &ADSR::UpdateAmp ) 00071 , mAmpValue(0) 00072 , mLevel(0) 00073 , mDLevel(0) 00074 , mStatus(Done) 00075 , mState( "State", this ) 00076 { 00077 Configure( cfg ); 00078 } 00079 00080 bool ADSR::ConcreteConfigure( const ProcessingConfig& c ) 00081 { 00082 CopyAsConcreteConfig(mConfig, c); 00083 00084 mAttackTime = mConfig.GetAttackTime(); 00085 mDecayTime = mConfig.GetDecayTime(); 00086 mSustainLevel = mConfig.GetSustainLevel(); 00087 mReleaseTime = mConfig.GetReleaseTime(); 00088 mSamplingRate = mConfig.GetSampleRate(); 00089 00090 return true; 00091 } 00092 00093 void ADSR::HandleAttack(void) 00094 { 00095 mStatus = Attack; 00096 mLevel = 0; 00097 mDLevel = mAmpValue / ( mAttackTime * mSamplingRate ); 00098 } 00099 00100 void ADSR::HandleDecay(void) 00101 { 00102 mStatus = Decay; 00103 mDLevel = ( mSustainLevel * mAmpValue - mAmpValue ) / ( mDecayTime * mSamplingRate ) ; 00104 } 00105 00106 void ADSR::HandleRelease(void) 00107 { 00108 mStatus = Release; 00109 mDLevel = - mLevel / ( mReleaseTime * mSamplingRate ); 00110 } 00111 00112 bool ADSR::Do( Audio& out) 00113 { 00114 /*** this is the "clean" version: 00115 00116 TData* ptr = out.GetBuffer().GetPtr(); 00117 00118 for ( int i = 0; i < out.GetSize() ; i++ ) 00119 { 00120 (*ptr++) = mLevel ; 00121 mLevel += mDLevel ; 00122 00123 if ( ( mStatus == Attack ) && ( mLevel >= mAmpValue ) ) 00124 { 00125 mStatus = Decay ; 00126 HandleDecay(); 00127 } 00128 else if ( ( mStatus == Decay ) && ( mLevel <= mSustainLevel ) ) 00129 { 00130 mStatus = Sustain ; 00131 mDLevel = 0 ; 00132 } 00133 else if ( ( mStatus == Release ) && ( mLevel <= 0 ) ) 00134 { 00135 mDLevel = 0; 00136 mLevel = 0; 00137 mStatus = Done; 00138 } 00139 } 00140 */ 00141 00142 /* 00143 the following does the same, but more efficient, by moving part of the conditions 00144 outside of the for loop 00145 */ 00146 00147 TData* ptr = out.GetBuffer().GetPtr(); 00148 TData* endptr = ptr+out.GetSize(); 00149 00150 if (mStatus==Attack) 00151 { 00152 while ( ptr!=endptr ) 00153 { 00154 (*ptr++) = mLevel ; 00155 mLevel += mDLevel ; 00156 00157 if (mLevel >= mAmpValue) 00158 { 00159 mStatus = Decay ; 00160 HandleDecay(); 00161 break; 00162 } 00163 } 00164 } 00165 if (mStatus==Decay) 00166 { 00167 while ( ptr!=endptr ) 00168 { 00169 (*ptr++) = mLevel ; 00170 mLevel += mDLevel ; 00171 00172 if (mLevel <= mSustainLevel ) 00173 { 00174 mStatus = Sustain ; 00175 mDLevel = 0 ; 00176 break; 00177 } 00178 } 00179 } 00180 if (mStatus==Sustain) 00181 { 00182 while ( ptr!=endptr ) 00183 { 00184 (*ptr++) = mLevel ; 00185 } 00186 } 00187 if (mStatus==Release) 00188 { 00189 while ( ptr!=endptr ) 00190 { 00191 (*ptr++) = mLevel ; 00192 mLevel += mDLevel ; 00193 00194 if (mLevel <=0 ) 00195 { 00196 mDLevel = 0; 00197 mLevel = 0; 00198 mStatus = Done; 00199 break; 00200 } 00201 } 00202 } 00203 if (mStatus==Done) 00204 { 00205 while ( ptr!=endptr ) 00206 { 00207 (*ptr++) = 0 ; 00208 } 00209 } 00210 00211 UpdateState(); 00212 00213 return true; 00214 00215 } 00216 00217 bool ADSR::Do() 00218 { 00219 bool res = false; 00220 res = Do(mOutput.GetAudio()); 00221 mOutput.Produce(); 00222 return res; 00223 00224 00225 } 00226 00227 } 00228