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         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 
Generated by  doxygen 1.6.3