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 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