00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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;
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