SpectralPeakDescriptors.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 
00023 
00024 
00025 #include "ProcessingData.hxx"
00026 #include "SpectralPeakDescriptors.hxx"
00027 #include "SpectralPeakArray.hxx"
00028 #include "CLAM_Math.hxx"
00029 
00030 namespace CLAM{
00031 
00032         DataArray Add(DataArray &a, DataArray &b);
00033         DataArray Multiply(TData &factor, DataArray &a);
00034         DataArray Multiply(DataArray &a, DataArray &b); // scalar product
00035 
00036 SpectralPeakDescriptors::SpectralPeakDescriptors(SpectralPeakArray* pSpectralPeakArray): Descriptor(eNumAttr)
00037 {
00038         CLAM_ASSERT(pSpectralPeakArray->GetScale()==EScale::eLinear,
00039                 "Spectral Peak Descriptors require a linear magnitude SpectralPeakArray");
00040         MandatoryInit();
00041         mpSpectralPeakArray=pSpectralPeakArray;
00042 }
00043 
00044 SpectralPeakDescriptors::SpectralPeakDescriptors(TData initVal):Descriptor(eNumAttr)
00045 {
00046         MandatoryInit();
00047         AddAll();
00048         UpdateData();
00049         
00050         SetMagnitudeMean(initVal);
00051         SetHarmonicCentroid(initVal);
00052         SetFirstTristimulus(initVal);
00053         SetSecondTristimulus(initVal);
00054         SetThirdTristimulus(initVal);
00055         SetHarmonicDeviation(initVal);
00056         SetOddHarmonics(initVal);
00057         SetEvenHarmonics(initVal);
00058         SetOddToEvenRatio(initVal);
00059 }
00060 
00061 void SpectralPeakDescriptors::DefaultInit() {
00062         mpSpectralPeakArray=0;
00063         mpStats=0;
00064 }
00065 
00066 void SpectralPeakDescriptors::CopyInit(const SpectralPeakDescriptors & copied) {
00067         mpSpectralPeakArray=copied.mpSpectralPeakArray;
00068         mpStats=0;
00069 }
00070 
00071 const SpectralPeakArray* SpectralPeakDescriptors::GetpSpectralPeakArray() const {
00072         return mpSpectralPeakArray;
00073 }
00074 
00075 void SpectralPeakDescriptors::SetpSpectralPeakArray(SpectralPeakArray* pSpectralPeakArray)
00076 {
00077         CLAM_ASSERT(pSpectralPeakArray->GetScale()==EScale::eLinear,
00078                 "Spectral Peak Descriptors require a linear magnitude SpectralPeakArray");
00079         mpSpectralPeakArray=pSpectralPeakArray;
00080     //TODO: it may give problems because pointer passed
00081         InitStats(&mpSpectralPeakArray->GetMagBuffer());
00082         mCentroid.Reset();
00083 }
00084 
00085 
00086 void SpectralPeakDescriptors::ConcreteCompute()
00087 {
00088 
00089         if (HasMagnitudeMean())
00090                 SetMagnitudeMean(mpStats->GetMean());
00091         if (HasHarmonicCentroid())
00092                 SetHarmonicCentroid(ComputeCentroid());
00093         if(HasFirstTristimulus())
00094                 SetFirstTristimulus(ComputeFirstTristimulus());
00095         if(HasSecondTristimulus())
00096                 SetSecondTristimulus(ComputeSecondTristimulus());
00097         if(HasThirdTristimulus())
00098                 SetThirdTristimulus(ComputeThirdTristimulus());
00099         if(HasHarmonicDeviation())
00100                 SetHarmonicDeviation(ComputeHarmonicDeviation());
00101         if(HasOddHarmonics())
00102                 SetOddHarmonics(ComputeOddHarmonics());
00103         if(HasEvenHarmonics())
00104                 SetEvenHarmonics(ComputeEvenHarmonics());
00105         if(HasOddToEvenRatio())
00106                 SetOddToEvenRatio(ComputeOddToEvenRatio());
00107 }
00108 
00109 TData SpectralPeakDescriptors::ComputeCentroid()
00110 {
00111         unsigned size = mpSpectralPeakArray->GetnPeaks();
00112         if (size<=0) return 0;
00113         const Array<TData> & magnitudes = mpSpectralPeakArray->GetMagBuffer();
00114         const Array<TData> & frequencies = mpSpectralPeakArray->GetFreqBuffer();
00115         TData crossProduct=0.0;
00116         for (unsigned i = 0; i < size; i++)
00117         {
00118                 crossProduct += magnitudes[i]*frequencies[i];
00119         }
00120         return crossProduct/(mpStats->GetMean()*size);
00121 }
00122 
00123 TData SpectralPeakDescriptors::ComputeFirstTristimulus()
00124 {
00125         if (mpSpectralPeakArray->GetnPeaks()<=0) return 0;
00126         const TData firstHarmonicMag=mpSpectralPeakArray->GetMagBuffer()[0];
00127         return firstHarmonicMag*firstHarmonicMag/mpStats->GetEnergy();
00128 }
00129 
00130 TData SpectralPeakDescriptors::ComputeSecondTristimulus()
00131 {
00132         if (mpSpectralPeakArray->GetnPeaks()<=3) return 0;
00133 
00134         const TData secondHarmonicMag=mpSpectralPeakArray->GetMagBuffer()[1];
00135         const TData thirdHarmonicMag=mpSpectralPeakArray->GetMagBuffer()[2];
00136         const TData fourthHarmonicMag=mpSpectralPeakArray->GetMagBuffer()[3];
00137         
00138         return (secondHarmonicMag*secondHarmonicMag+thirdHarmonicMag*thirdHarmonicMag+
00139                         fourthHarmonicMag*fourthHarmonicMag)/mpStats->GetEnergy();
00140 }
00141 
00142 TData SpectralPeakDescriptors::ComputeThirdTristimulus()
00143 {
00144         if (mpSpectralPeakArray->GetnPeaks()<=4) return 0;
00145         const DataArray& a=mpSpectralPeakArray->GetMagBuffer();
00146         return accumulate(a.GetPtr()+4,a.GetPtr()+a.Size(),0.,Power<2>())/mpStats->GetEnergy(); 
00147 }
00148 
00149 TData SpectralPeakDescriptors::ComputeHarmonicDeviation()
00150 {
00151         const unsigned size=mpSpectralPeakArray->GetnPeaks();
00152         if (size<4) return 0.0; //is it really necessary to have 4 or with 2 is enough
00153         const DataArray & data=mpSpectralPeakArray->GetMagBuffer();
00154 
00155         TData denom = 0;
00156         TData nom = 0;
00157 
00158         const TData tmp0 = log10((data[0]+data[1])/2);
00159         const TData logdata0=log10(data[0]);
00160         denom += logdata0;
00161         nom +=  CLAM::Abs(logdata0 - tmp0);
00162         
00163         for (unsigned i=1;i<size-1;i++)
00164         {
00165                 const TData tmpi = log10((data[i-1]+data[i]+data[i+1])/3);
00166                 const TData logdatai=log10(data[i]);
00167                 denom += logdatai;
00168                 nom +=  CLAM::Abs(logdatai - tmpi);
00169         }
00170 
00171         const TData tmpN = log10((data[size-2]+data[size-1])/2);
00172         const TData logdataN=log10(data[size-1]);
00173         denom += logdataN;
00174         nom +=  CLAM::Abs(logdataN - tmpN);
00175 
00176         return nom/denom;       
00177 }
00178 
00179 TData SpectralPeakDescriptors::ComputeOddHarmonics()
00180 {
00181         const unsigned size=mpSpectralPeakArray->GetnPeaks();
00182         if (size<3) return 0;
00183         const DataArray& data=mpSpectralPeakArray->GetMagBuffer();
00184         TData oddEnergy = 0.0;
00185         for (unsigned i=2;i<size;i+=2)
00186         {
00187                 oddEnergy+=data[i]*data[i];
00188         }
00189         return oddEnergy/mpStats->GetEnergy();
00190 }
00191 
00192 TData SpectralPeakDescriptors::ComputeEvenHarmonics()
00193 {
00194         const unsigned size=mpSpectralPeakArray->GetnPeaks();
00195         if (size<2) return 0;
00196         const DataArray& data=mpSpectralPeakArray->GetMagBuffer();
00197         TData evenEnergy = 0.0;
00198         for (unsigned i=1;i<size;i+=2)
00199         {
00200                 evenEnergy+=data[i]*data[i];
00201         }
00202         return evenEnergy/mpStats->GetEnergy();
00203 }
00204 
00205 TData SpectralPeakDescriptors::ComputeOddToEvenRatio()
00206 {
00207         if (mpSpectralPeakArray->GetnPeaks()<=1) return 0.5;
00208         TData odd,even;
00209         if (HasOddHarmonics()) odd=GetOddHarmonics();
00210         else odd=ComputeOddHarmonics();
00211         if (HasEvenHarmonics()) even=GetEvenHarmonics();
00212         else even=ComputeEvenHarmonics();
00213 
00214         return odd/(even+odd);
00215 }
00216 
00217 SpectralPeakDescriptors operator * (const SpectralPeakDescriptors& a,TData mult) 
00218 {
00219         SpectralPeakDescriptors tmpD(a);
00220 
00221         if (a.HasMagnitudeMean())
00222         {
00223                 tmpD.SetMagnitudeMean(a.GetMagnitudeMean()*mult);
00224         }
00225         if (a.HasHarmonicCentroid())
00226         {
00227                 tmpD.SetHarmonicCentroid(a.GetHarmonicCentroid()*mult);
00228         }
00229         if (a.HasFirstTristimulus())
00230         {
00231                 tmpD.SetFirstTristimulus(a.GetFirstTristimulus()*mult);
00232         }
00233         if (a.HasSecondTristimulus())
00234         {
00235                 tmpD.SetSecondTristimulus(a.GetSecondTristimulus()*mult);
00236         }
00237         if (a.HasThirdTristimulus())
00238         {
00239                 tmpD.SetThirdTristimulus(a.GetThirdTristimulus()*mult);
00240         }
00241         if (a.HasHarmonicDeviation())
00242         {
00243                 tmpD.SetHarmonicDeviation(a.GetHarmonicDeviation()*mult);
00244         }
00245         if (a.HasOddHarmonics())
00246         {
00247                 tmpD.SetOddHarmonics(a.GetOddHarmonics()*mult);
00248         }
00249         if (a.HasEvenHarmonics())
00250         {
00251                 tmpD.SetEvenHarmonics(a.GetEvenHarmonics()*mult);
00252         }
00253         if (a.HasOddToEvenRatio())
00254         {
00255                 tmpD.SetOddToEvenRatio(a.GetOddToEvenRatio()*mult);
00256         }
00257         if(a.HasHPCP())
00258                 tmpD.SetHPCP(Multiply(mult,a.GetHPCP()));
00259 
00260         return tmpD;
00261 }
00262 
00263 SpectralPeakDescriptors operator * (const SpectralPeakDescriptors& a,const SpectralPeakDescriptors& b) 
00264 {
00265         SpectralPeakDescriptors tmpD;
00266 
00267         if (a.HasMagnitudeMean() && b.HasMagnitudeMean())
00268         {
00269                 tmpD.AddMagnitudeMean();
00270                 tmpD.UpdateData();
00271                 tmpD.SetMagnitudeMean(a.GetMagnitudeMean()*b.GetMagnitudeMean());
00272         }
00273         if (a.HasHarmonicCentroid() && b.HasHarmonicCentroid())
00274         {
00275                 tmpD.AddHarmonicCentroid();
00276                 tmpD.UpdateData();
00277                 tmpD.SetHarmonicCentroid(a.GetHarmonicCentroid()*b.GetHarmonicCentroid());
00278         }
00279         if (a.HasFirstTristimulus() && b.HasFirstTristimulus())
00280         {
00281                 tmpD.AddFirstTristimulus();
00282                 tmpD.UpdateData();
00283                 tmpD.SetFirstTristimulus(a.GetFirstTristimulus()*b.GetFirstTristimulus());
00284         }
00285         if (a.HasSecondTristimulus() && b.HasSecondTristimulus())
00286         {
00287                 tmpD.AddSecondTristimulus();
00288                 tmpD.UpdateData();
00289                 tmpD.SetSecondTristimulus(a.GetSecondTristimulus()*b.GetSecondTristimulus());
00290         }
00291         if (a.HasThirdTristimulus() && b.HasThirdTristimulus())
00292         {
00293                 tmpD.AddThirdTristimulus();
00294                 tmpD.UpdateData();
00295                 tmpD.SetThirdTristimulus(a.GetThirdTristimulus()*b.GetThirdTristimulus());
00296         }
00297         if (a.HasHarmonicDeviation() && b.HasHarmonicDeviation())
00298         {
00299                 tmpD.AddHarmonicDeviation();
00300                 tmpD.UpdateData();
00301                 tmpD.SetHarmonicDeviation(a.GetHarmonicDeviation()*b.GetHarmonicDeviation());
00302         }
00303         if (a.HasOddHarmonics() && b.HasOddHarmonics())
00304         {
00305                 tmpD.AddOddHarmonics();
00306                 tmpD.UpdateData();
00307                 tmpD.SetOddHarmonics(a.GetOddHarmonics()*b.GetOddHarmonics());
00308         }
00309         if (a.HasEvenHarmonics() && b.HasEvenHarmonics())
00310         {
00311                 tmpD.AddEvenHarmonics();
00312                 tmpD.UpdateData();
00313                 tmpD.SetEvenHarmonics(a.GetEvenHarmonics()*b.GetEvenHarmonics());
00314         }
00315         if (a.HasOddToEvenRatio() && b.HasOddToEvenRatio())
00316         {
00317                 tmpD.AddOddToEvenRatio();
00318                 tmpD.UpdateData();
00319                 tmpD.SetOddToEvenRatio(a.GetOddToEvenRatio()*b.GetOddToEvenRatio());
00320         }
00321         if (a.HasHPCP() && b.HasHPCP())
00322         {
00323                 tmpD.AddHPCP();
00324                 tmpD.UpdateData();
00325                 tmpD.SetHPCP(Multiply(a.GetHPCP(),b.GetHPCP()));
00326         }
00327         
00328         return tmpD;
00329 }
00330 
00331 SpectralPeakDescriptors operator + (const SpectralPeakDescriptors& a,const SpectralPeakDescriptors& b)
00332 {
00333         SpectralPeakDescriptors tmpD;
00334 
00335         if (a.HasMagnitudeMean() && b.HasMagnitudeMean())
00336         {
00337                 tmpD.AddMagnitudeMean();
00338                 tmpD.UpdateData();
00339                 tmpD.SetMagnitudeMean(a.GetMagnitudeMean()+b.GetMagnitudeMean());
00340         }
00341         if (a.HasHarmonicCentroid() && b.HasHarmonicCentroid())
00342         {
00343                 tmpD.AddHarmonicCentroid();
00344                 tmpD.UpdateData();
00345                 tmpD.SetHarmonicCentroid(a.GetHarmonicCentroid()+b.GetHarmonicCentroid());
00346         }
00347         if (a.HasFirstTristimulus() && b.HasFirstTristimulus())
00348         {
00349                 tmpD.AddFirstTristimulus();
00350                 tmpD.UpdateData();
00351                 tmpD.SetFirstTristimulus(a.GetFirstTristimulus()+b.GetFirstTristimulus());
00352         }
00353         if (a.HasSecondTristimulus() && b.HasSecondTristimulus())
00354         {
00355                 tmpD.AddSecondTristimulus();
00356                 tmpD.UpdateData();
00357                 tmpD.SetSecondTristimulus(a.GetSecondTristimulus()+b.GetSecondTristimulus());
00358         }
00359         if (a.HasThirdTristimulus() && b.HasThirdTristimulus())
00360         {
00361                 tmpD.AddThirdTristimulus();
00362                 tmpD.UpdateData();
00363                 tmpD.SetThirdTristimulus(a.GetThirdTristimulus()+b.GetThirdTristimulus());
00364         }
00365         if (a.HasHarmonicDeviation() && b.HasHarmonicDeviation())
00366         {
00367                 tmpD.AddHarmonicDeviation();
00368                 tmpD.UpdateData();
00369                 tmpD.SetHarmonicDeviation(a.GetHarmonicDeviation()+b.GetHarmonicDeviation());
00370         }
00371         if (a.HasOddHarmonics() && b.HasOddHarmonics())
00372         {
00373                 tmpD.AddOddHarmonics();
00374                 tmpD.UpdateData();
00375                 tmpD.SetOddHarmonics(a.GetOddHarmonics()+b.GetOddHarmonics());
00376         }
00377         if (a.HasEvenHarmonics() && b.HasEvenHarmonics())
00378         {
00379                 tmpD.AddEvenHarmonics();
00380                 tmpD.UpdateData();
00381                 tmpD.SetEvenHarmonics(a.GetEvenHarmonics()+b.GetEvenHarmonics());
00382         }
00383         if (a.HasOddToEvenRatio() && b.HasOddToEvenRatio())
00384         {
00385                 tmpD.AddOddToEvenRatio();
00386                 tmpD.UpdateData();
00387                 tmpD.SetOddToEvenRatio(a.GetOddToEvenRatio()+b.GetOddToEvenRatio());
00388         }
00389         if(a.HasHPCP() && b.HasHPCP() )
00390         {
00391                 tmpD.AddHPCP();
00392                 tmpD.UpdateData();
00393                 tmpD.SetHPCP(Add(a.GetHPCP(),b.GetHPCP()));
00394         }
00395 
00396         
00397         return tmpD;
00398 }
00399 
00400 SpectralPeakDescriptors operator / (const SpectralPeakDescriptors& a,TData div) 
00401 {
00402         return a*(1/div);
00403 }
00404 
00405 SpectralPeakDescriptors operator * (TData mult, const SpectralPeakDescriptors& a) 
00406 {
00407         return a*mult;
00408 }
00409 
00410 }//CLAM
00411 
Generated by  doxygen 1.6.3