00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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);
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
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;
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 }
00411