|
CLAM-Development
1.3
|
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 #include "EnvelopeExtractor.hxx" 00023 00024 00025 namespace CLAM { 00026 00027 void IntervalAmplitudeAverages::Reconfigure(int points_per_frame,int memory_points) 00028 { 00029 int new_size = points_per_frame + memory_points; 00030 00031 if (mArray.Size() < new_size) 00032 mArray.Resize(new_size); 00033 00034 if (mArray.Size() != new_size) 00035 mArray.SetSize(new_size); 00036 00037 mCurrentPos = memory_points-1; 00038 mNMemoryPoints = memory_points; 00039 mPointsPerFrame = points_per_frame; 00040 } 00041 00042 bool IntervalAmplitudeAverages::Configured() 00043 { 00044 return mArray.Size() != 0; 00045 } 00046 00047 TData &IntervalAmplitudeAverages::Current(int index) 00048 { 00049 return mArray[mCurrentPos+index]; 00050 } 00051 00052 void IntervalAmplitudeAverages::Clear() 00053 { 00054 int i, npoints = mArray.Size(); 00055 for (i=0; i<npoints; i++) 00056 mArray[i]=0.0; 00057 } 00058 00059 void IntervalAmplitudeAverages::AdvanceFrame() 00060 { 00061 for (int i = -mCurrentPos; i<=0; i++) 00062 Current(i) = Current(i+mPointsPerFrame); 00063 } 00064 00065 void IntervalAmplitudeAverages::Compute(int interval, 00066 Array<TData> &audio, 00067 int interval_start, 00068 int interval_end) 00069 { 00070 TData interval_mean = 0.0; 00071 for (int i=interval_start; i<interval_end; i++) 00072 interval_mean += fabs(audio[i]); 00073 interval_mean /= interval_end - interval_start; 00074 Current(interval) = interval_mean; 00075 } 00076 00077 TData IntervalAmplitudeAverages::AcumulationShape(int i) 00078 { 00079 return TData(mNMemoryPoints-i)/TData(mNMemoryPoints); 00080 } 00081 00082 TData IntervalAmplitudeAverages::Acumulated(int ipoint) 00083 { 00084 TData res =0.0; 00085 for (unsigned i=0; i< mNMemoryPoints; i++) 00086 res += AcumulationShape(i) * Current(ipoint-i); 00087 return res; 00088 } 00089 00090 00091 void EnvExtractorConfig::DefaultInit() 00092 { 00093 AddAll(); 00094 UpdateData(); 00095 SetSampleRate(44100); 00096 SetFrameSize(512); 00097 00098 GetInterpolationPeriod().SetInitValue(5.0); 00099 GetInterpolationPeriod().SetMinValue(2.0); 00100 GetInterpolationPeriod().SetMaxValue(10.0); 00101 00102 GetIntegrationLength().SetInitValue(50.0); 00103 GetIntegrationLength().SetMinValue(10.0); 00104 GetIntegrationLength().SetMaxValue(2000.0); 00105 00106 GetNormalLevel().SetInitValue(0.25); 00107 GetNormalLevel().SetMinValue(0.01); 00108 GetNormalLevel().SetMaxValue(10.0); 00109 00110 GetSilenceLevel().SetInitValue(0.0); 00111 GetSilenceLevel().SetMinValue(0.0); 00112 GetSilenceLevel().SetMaxValue(0.2); 00113 00114 SetNInterpPointsPerFrame(0); 00115 SetNMemoryPoints(0); 00116 SetInterpolationType(EInterpolation::eLinear); 00117 } 00118 00119 #define CONTROL(name) c##name(#name,this,&EnvelopeExtractor::name##Change) 00120 00121 EnvelopeExtractor::EnvelopeExtractor(const EnvExtractorConfig& c) 00122 : CONTROL(InterpolationPeriod) 00123 , CONTROL(IntegrationLength) 00124 , CONTROL(NormalLevel) 00125 , CONTROL(SilenceLevel) 00126 , Input("Input",this) 00127 , Output("Output",this) 00128 , mPointsPerFrame(0) 00129 , mNMemoryPoints(0) 00130 , mNormalLevel(0.0) 00131 , mSilenceLevel(0.0) 00132 , mDeltaX(0.0) 00133 , mFrameTime(0.0) 00134 , mFrameSize(0) 00135 , mInterpolationPeriod(0.0) 00136 , mIntegrationLength(0.0) 00137 , mIsSpline(false) 00138 { 00139 Configure(c); 00140 } 00141 00142 #undef CONTROL 00143 00144 bool EnvelopeExtractor::ConcreteStart() 00145 { 00146 if (!mAmplitudeAverages.Configured()) 00147 return false; 00148 00149 mAmplitudeAverages.Clear(); 00150 00151 int i,n_interp_points; 00152 00153 if (mIsSpline) n_interp_points = mPointsPerFrame + 3; 00154 else n_interp_points = mPointsPerFrame + 1; 00155 for (i=0; i<n_interp_points; i++) 00156 mInterpolationPoints[i]=0.0; 00157 00158 return true; 00159 } 00160 00161 void EnvelopeExtractor::ConfigureEnvelope(BPFTmpl<TTime,TData> & bpf) 00162 { 00163 if (bpf.Size() != mPointsPerFrame+1) { 00164 bpf.Resize (mPointsPerFrame+1); 00165 bpf.SetSize (mPointsPerFrame+1); 00166 } 00167 00168 if (bpf.GetInterpolation() != mConfig.GetInterpolationType()) 00169 bpf.SetIntpType(mConfig.GetInterpolationType()); 00170 00171 double pos=0.0; 00172 int i; 00173 for (i=0; i<=mPointsPerFrame; i++) { 00174 bpf.SetXValue(i,pos); 00175 pos+=mDeltaX; 00176 } 00177 } 00178 00179 bool EnvelopeExtractor::SetPointsPerFrame(int npoints) 00180 { 00181 if ( ( npoints < 1 ) || 00182 ( npoints < 2 && mIsSpline ) ) 00183 { 00184 return false; 00185 } 00186 00187 mPointsPerFrame = npoints; 00188 00189 int n_interp_points = mPointsPerFrame + 1; 00190 00191 if (mIsSpline) 00192 n_interp_points +=2; // Needed for boundary derivatives 00193 00194 if (mInterpolationPoints.AllocatedSize() < n_interp_points) 00195 mInterpolationPoints.Resize(n_interp_points); 00196 00197 mInterpolationPoints.SetSize(n_interp_points); 00198 00199 mAmplitudeAverages.Reconfigure(mPointsPerFrame,mNMemoryPoints); 00200 00201 mDeltaX = (mSampleDelta * TTime(mFrameSize)) / TTime(mPointsPerFrame); 00202 00203 return true; 00204 } 00205 00206 bool EnvelopeExtractor::SetInterpolationPeriod(TTime period) 00207 { 00208 int points_per_frame = int(mFrameTime / period); 00209 00210 if (!SetPointsPerFrame(points_per_frame)) 00211 return false; 00212 00213 mInterpolationPeriod = period; 00214 00215 return true; 00216 } 00217 00218 void EnvelopeExtractor::SetNMemoryPoints(int mpoints) 00219 { 00220 mNMemoryPoints = mpoints; 00221 00222 mAmplitudeAverages.Reconfigure(mPointsPerFrame,mNMemoryPoints); 00223 } 00224 00225 bool EnvelopeExtractor::SetIntegrationLength(TTime length) 00226 { 00227 int memory_points = int(length / mInterpolationPeriod); 00228 00229 if (memory_points <= 0) 00230 return false; 00231 00232 mIntegrationLength = length; 00233 00234 SetNMemoryPoints(memory_points); 00235 00236 return true; 00237 } 00238 00239 void EnvelopeExtractor::SetNormalLevel(TData nlevel) 00240 { 00241 mNormalLevel = nlevel; 00242 } 00243 00244 void EnvelopeExtractor::SetSilenceLevel(TData slevel) 00245 { 00246 mSilenceLevel = slevel; 00247 } 00248 00249 bool EnvelopeExtractor::ConcreteConfigure(const ProcessingConfig& c) 00250 { 00251 CopyAsConcreteConfig(mConfig, c); 00252 00253 mIsSpline = (mConfig.GetInterpolationType() == EInterpolation::eSpline); 00254 00255 mFrameSize = mConfig.GetFrameSize(); 00256 00257 if (!mFrameSize) 00258 { 00259 AddConfigErrorMessage("FrameSize must be non-zero"); 00260 return false; 00261 } 00262 00263 mFrameTime = 1000.0 * double(mFrameSize) / double(mConfig.GetSampleRate()); 00264 00265 if (mConfig.GetNInterpPointsPerFrame() > 0) 00266 { 00267 SetPointsPerFrame(mConfig.GetNInterpPointsPerFrame()); 00268 } 00269 else if (mConfig.GetInterpolationPeriod().GetInitValue() > 0.0) 00270 { 00271 if (!SetInterpolationPeriod(mConfig.GetInterpolationPeriod().GetInitValue())) 00272 { 00273 AddConfigErrorMessage("The interpolation period requested in config would require\n" 00274 "less than one interpolation point per frame"); 00275 return false; 00276 } 00277 } 00278 else { 00279 AddConfigErrorMessage("Neither the number of interpolation points per frame nor the \n" 00280 "interpolation period requested in configuration are valid."); 00281 return false; 00282 } 00283 00284 if (mConfig.GetNMemoryPoints() > 0 ) 00285 { 00286 SetNMemoryPoints(mConfig.GetNMemoryPoints()); 00287 } 00288 else if ( mConfig.GetIntegrationLength().GetInitValue() > 0.0 ) 00289 { 00290 if (!SetIntegrationLength(mConfig.GetIntegrationLength().GetInitValue())) 00291 { 00292 AddConfigErrorMessage("The integration length requested leads" 00293 "to a non-positive number of memory points."); 00294 return false; 00295 } 00296 } 00297 else 00298 { 00299 AddConfigErrorMessage("Neither the integration length nor the number of memory points" 00300 "requested in configuration are valid."); 00301 return false; 00302 } 00303 00304 SetNormalLevel(mConfig.GetNormalLevel().GetInitValue()); 00305 00306 SetSilenceLevel(mConfig.GetSilenceLevel().GetInitValue()); 00307 00308 mSampleDelta = 1000.0 / (TTime)mConfig.GetSampleRate(); 00309 00310 mDeltaX = (mSampleDelta * TTime(mFrameSize)) / TTime(mPointsPerFrame); 00311 00312 InitializeControls(); 00313 00314 Input.SetSize(mFrameSize); 00315 return true; 00316 } 00317 00318 void EnvelopeExtractor::CleanSilence() 00319 { 00320 int i,first,end; 00321 00322 if (mIsSpline) { 00323 first = 3; 00324 end = mPointsPerFrame+2; 00325 } 00326 else { 00327 first = 1; 00328 end = mPointsPerFrame; 00329 } 00330 00331 for (i=first; i<=end; i++) 00332 if (mInterpolationPoints[i] < mSilenceLevel) 00333 mInterpolationPoints[i] = 0.0; 00334 else 00335 mInterpolationPoints[i] -= mSilenceLevel; 00336 } 00337 00338 void EnvelopeExtractor::WriteEnvelope(BPFTmpl<TTime,TData> &bpf) 00339 { 00340 int i,ipos; 00341 00342 if (mIsSpline) ipos=1; 00343 else ipos=0; 00344 00345 for (i=0; i<=mPointsPerFrame; i++) 00346 bpf.SetValue(i,mInterpolationPoints[ipos++]); 00347 00348 if (mIsSpline) { 00349 bpf.SetLeftDerivative( 00350 (mInterpolationPoints[2]-mInterpolationPoints[0]) / mDeltaX); 00351 bpf.SetRightDerivative( 00352 (mInterpolationPoints[mPointsPerFrame+2] - 00353 mInterpolationPoints[mPointsPerFrame] ) / mDeltaX); 00354 bpf.UpdateSplineTable(); 00355 } 00356 } 00357 00358 void EnvelopeExtractor::StoreInterpolationPoints() 00359 { 00360 mInterpolationPoints[0] = mInterpolationPoints[mPointsPerFrame]; 00361 if (mIsSpline) { 00362 mInterpolationPoints[1] = mInterpolationPoints[mPointsPerFrame+1]; 00363 mInterpolationPoints[2] = mInterpolationPoints[mPointsPerFrame+2]; 00364 } 00365 } 00366 00367 00368 00369 00370 void EnvelopeExtractor::InterpolationPeriodChange(TControlData val) 00371 { 00372 SetInterpolationPeriod(mIpMin + val * mIpFactor); 00373 mInterpolationPeriodControl = val; 00374 } 00375 00376 void EnvelopeExtractor::IntegrationLengthChange(TControlData val) 00377 { 00378 SetIntegrationLength(mIlMin + val * mIlFactor); 00379 mIntegrationLengthControl = val; 00380 } 00381 00382 void EnvelopeExtractor::NormalLevelChange(TControlData val) 00383 { 00384 SetNormalLevel(mNlMin + val * mNlFactor); 00385 mNormalLevelControl = val; 00386 } 00387 00388 void EnvelopeExtractor::SilenceLevelChange(TControlData val) 00389 { 00390 SetSilenceLevel(mSlMin + val * mSlFactor); 00391 mSilenceLevelControl = val; 00392 } 00393 00394 void EnvelopeExtractor::InitializeControls(void) 00395 { 00396 mIpMin = mConfig.GetInterpolationPeriod().GetMinValue(); 00397 mIpFactor = mConfig.GetInterpolationPeriod().GetMaxValue() - mIpMin; 00398 mInterpolationPeriodControl = 00399 (mConfig.GetInterpolationPeriod().GetInitValue() -mIpMin) / mIpFactor; 00400 00401 mIlMin = mConfig.GetIntegrationLength().GetMinValue(); 00402 mIlFactor = mConfig.GetIntegrationLength().GetMaxValue() - mIlMin; 00403 mIntegrationLengthControl = 00404 (mConfig.GetIntegrationLength().GetInitValue() - mIlMin) / mIlFactor; 00405 00406 mNlMin = mConfig.GetNormalLevel().GetMinValue(); 00407 mNlFactor = mConfig.GetNormalLevel().GetMaxValue() - mNlMin; 00408 mNormalLevelControl = 00409 (mConfig.GetNormalLevel().GetInitValue() - mNlMin) / mNlFactor; 00410 00411 mSlMin = mConfig.GetSilenceLevel().GetMinValue(); 00412 mSlFactor = mConfig.GetSilenceLevel().GetMaxValue() - mSlMin; 00413 mSilenceLevelControl = 00414 (mConfig.GetSilenceLevel().GetInitValue() - mSlMin) / mSlFactor; 00415 00416 } 00417 00418 bool EnvelopeExtractor::Do() 00419 { 00420 bool res = Do(Input.GetData(),Output.GetData()); 00421 Input.Consume(); 00422 Output.Produce(); 00423 return res; 00424 } 00425 00426 bool EnvelopeExtractor::Do(const Audio& inp, Envelope& env) 00427 { 00428 CLAM_ASSERT(inp.GetSize() == mFrameSize, 00429 "EnvelopeExtractor::Do(): Wrong audio size."); 00430 00431 Array<TData> &audio = inp.GetBuffer(); 00432 BPFTmpl<TTime,TData> &bpf = env.GetAmplitudeBPF(); 00433 int i,ipos,interval_start=0, interval_end; 00434 00435 ConfigureEnvelope(bpf); 00436 00437 if (mIsSpline) ipos=3; 00438 else ipos=1; 00439 00440 for (i=1; i<=mPointsPerFrame; i++) { 00441 interval_end = (mFrameSize*i)/mPointsPerFrame; 00442 mAmplitudeAverages.Compute(i,audio,interval_start,interval_end); 00443 interval_start = interval_end; 00444 mInterpolationPoints[ipos++] = mAmplitudeAverages.Acumulated(i) / 00445 (mNMemoryPoints*mNormalLevel); 00446 } 00447 if (mSilenceLevel > 0.0) 00448 CleanSilence(); 00449 WriteEnvelope(bpf); 00450 StoreInterpolationPoints(); 00451 mAmplitudeAverages.AdvanceFrame(); 00452 return true; 00453 } 00454 } 00455
1.7.6.1