EnvelopeExtractor.cxx

Go to the documentation of this file.
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 

Generated on Tue Aug 12 22:33:42 2008 for CLAM by  doxygen 1.5.5