CLAM-Development
1.1
|
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