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 #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 int EnvelopeExtractor::InterpolationPeriodChange(TControlData val) 00371 { 00372 SetInterpolationPeriod(mIpMin + val * mIpFactor); 00373 mInterpolationPeriodControl = val; 00374 return 0; 00375 } 00376 00377 int EnvelopeExtractor::IntegrationLengthChange(TControlData val) 00378 { 00379 SetIntegrationLength(mIlMin + val * mIlFactor); 00380 mIntegrationLengthControl = val; 00381 return 0; 00382 } 00383 00384 int EnvelopeExtractor::NormalLevelChange(TControlData val) 00385 { 00386 SetNormalLevel(mNlMin + val * mNlFactor); 00387 mNormalLevelControl = val; 00388 return 0; 00389 } 00390 00391 int EnvelopeExtractor::SilenceLevelChange(TControlData val) 00392 { 00393 SetSilenceLevel(mSlMin + val * mSlFactor); 00394 mSilenceLevelControl = val; 00395 return 0; 00396 } 00397 00398 void EnvelopeExtractor::InitializeControls(void) 00399 { 00400 mIpMin = mConfig.GetInterpolationPeriod().GetMinValue(); 00401 mIpFactor = mConfig.GetInterpolationPeriod().GetMaxValue() - mIpMin; 00402 mInterpolationPeriodControl = 00403 (mConfig.GetInterpolationPeriod().GetInitValue() -mIpMin) / mIpFactor; 00404 00405 mIlMin = mConfig.GetIntegrationLength().GetMinValue(); 00406 mIlFactor = mConfig.GetIntegrationLength().GetMaxValue() - mIlMin; 00407 mIntegrationLengthControl = 00408 (mConfig.GetIntegrationLength().GetInitValue() - mIlMin) / mIlFactor; 00409 00410 mNlMin = mConfig.GetNormalLevel().GetMinValue(); 00411 mNlFactor = mConfig.GetNormalLevel().GetMaxValue() - mNlMin; 00412 mNormalLevelControl = 00413 (mConfig.GetNormalLevel().GetInitValue() - mNlMin) / mNlFactor; 00414 00415 mSlMin = mConfig.GetSilenceLevel().GetMinValue(); 00416 mSlFactor = mConfig.GetSilenceLevel().GetMaxValue() - mSlMin; 00417 mSilenceLevelControl = 00418 (mConfig.GetSilenceLevel().GetInitValue() - mSlMin) / mSlFactor; 00419 00420 } 00421 00422 bool EnvelopeExtractor::Do() 00423 { 00424 bool res = Do(Input.GetData(),Output.GetData()); 00425 Input.Consume(); 00426 Output.Produce(); 00427 return res; 00428 } 00429 00430 bool EnvelopeExtractor::Do(const Audio& inp, Envelope& env) 00431 { 00432 CLAM_ASSERT(inp.GetSize() == mFrameSize, 00433 "EnvelopeExtractor::Do(): Wrong audio size."); 00434 00435 Array<TData> &audio = inp.GetBuffer(); 00436 BPFTmpl<TTime,TData> &bpf = env.GetAmplitudeBPF(); 00437 int i,ipos,interval_start=0, interval_end; 00438 00439 ConfigureEnvelope(bpf); 00440 00441 if (mIsSpline) ipos=3; 00442 else ipos=1; 00443 00444 for (i=1; i<=mPointsPerFrame; i++) { 00445 interval_end = (mFrameSize*i)/mPointsPerFrame; 00446 mAmplitudeAverages.Compute(i,audio,interval_start,interval_end); 00447 interval_start = interval_end; 00448 mInterpolationPoints[ipos++] = mAmplitudeAverages.Acumulated(i) / 00449 (mNMemoryPoints*mNormalLevel); 00450 } 00451 if (mSilenceLevel > 0.0) 00452 CleanSilence(); 00453 WriteEnvelope(bpf); 00454 StoreInterpolationPoints(); 00455 mAmplitudeAverages.AdvanceFrame(); 00456 return true; 00457 } 00458 } 00459