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 #include "SpectralDescriptors.hxx" 00023 #include "Spectrum.hxx" 00024 #include "Array.hxx" 00025 #include <algorithm> 00026 00027 namespace CLAM{ 00028 00029 DataArray Add(DataArray &a, DataArray &b) { 00030 TIndex i; 00031 TSize sizea=a.Size(); 00032 TSize sizeb=b.Size(); 00033 TSize size; 00034 DataArray result; 00035 00036 // One has size==0 (optimized with respect to the following case?) 00037 if (sizea==0) { 00038 result=b; 00039 return result; 00040 } 00041 if (sizeb==0) { 00042 result=a; 00043 return result; 00044 } 00045 00046 // Different sizes 00047 if(sizea != sizeb) { 00048 if (sizea < sizeb) { 00049 size=sizeb; 00050 result.Resize(size); 00051 result.SetSize(size); 00052 for (i=0; i<sizea; i++) 00053 result[i]=a[i]+b[i]; 00054 for (i=sizea; i<sizeb; i++) 00055 result[i]=b[i]; 00056 return result; 00057 } 00058 else { // sizea>sizeb 00059 size=sizea; 00060 result.Resize(size); 00061 result.SetSize(size); 00062 for (i=0; i<sizeb; i++) 00063 result[i]=a[i]+b[i]; 00064 for (i=sizeb; i<sizea; i++) 00065 result[i]=a[i]; 00066 return result; 00067 } 00068 } 00069 // Equal size 00070 size=sizea; 00071 result.Resize(size); 00072 result.SetSize(size); 00073 for (i=0; i<size; i++) 00074 result[i]=a[i]+b[i]; 00075 return result; 00076 } 00077 00078 DataArray Multiply(TData &factor, DataArray &a) { 00079 TIndex i; 00080 TSize size=a.Size(); 00081 DataArray result; 00082 result.Resize(size); 00083 result.SetSize(size); 00084 for (i=0; i<size; i++) 00085 result[i]=factor*a[i]; 00086 return result; 00087 } 00088 00089 /* Scalar product of two vectors */ 00090 DataArray Multiply(DataArray &a, DataArray &b) { 00091 TIndex i; 00092 TSize size=a.Size(); 00093 DataArray result; 00094 result.Resize(size); 00095 result.SetSize(size); 00096 for (i=0; i<size; i++) 00097 result[i]=a[i]*b[i]; 00098 return result; 00099 } 00100 00101 SpectralDescriptors::SpectralDescriptors(Spectrum* pSpectrum):Descriptor(eNumAttr) 00102 { 00103 CLAM_ASSERT(pSpectrum->GetScale()==EScale::eLinear, 00104 "Spectral Descriptors require a linear magnitude Spectrum"); 00105 MandatoryInit(); 00106 mpSpectrum=pSpectrum; 00107 } 00108 00109 SpectralDescriptors::SpectralDescriptors(TData initVal):Descriptor(eNumAttr) 00110 { 00111 MandatoryInit(); 00112 AddAll(); 00113 UpdateData(); 00114 SetMean(initVal); 00115 SetGeometricMean(initVal); 00116 SetEnergy(initVal); 00117 SetCentroid(initVal); 00118 SetMoment2(initVal); 00119 SetMoment3(initVal); 00120 SetMoment4(initVal); 00121 SetMoment5(initVal); 00122 SetMoment6(initVal); 00123 SetSpread(initVal); 00124 SetMagnitudeSkewness(initVal); 00125 SetMagnitudeKurtosis(initVal); 00126 SetFlatness(initVal); 00127 SetHighFrequencyContent(initVal); 00128 SetMaxMagFreq(initVal); 00129 SetLowFreqEnergyRelation(initVal); 00130 SetRolloff(initVal); 00131 SetSlope(initVal); 00132 } 00133 00134 void SpectralDescriptors::DefaultInit() { 00135 mpSpectrum=0; 00136 mpStats=0; 00137 //Warning: no attributes are added by default, the user is in charge of adding the ones he is interested in 00138 } 00139 00140 void SpectralDescriptors::CopyInit(const SpectralDescriptors & copied) 00141 { 00142 mpSpectrum=copied.mpSpectrum; 00143 mpStats=0; 00144 } 00145 00146 const Spectrum* SpectralDescriptors::GetpSpectrum() const 00147 { 00148 return mpSpectrum; 00149 } 00150 00151 void SpectralDescriptors::SetpSpectrum(Spectrum* pSpectrum) 00152 { 00153 00154 CLAM_ASSERT(pSpectrum->GetScale()==EScale::eLinear, 00155 "Spectral Descriptors require a linear magnitude Spectrum"); 00156 mpSpectrum=pSpectrum; 00157 //TODO: we are asuming Spectrum is in MagBuffer 00158 //TODO: it may give problems because pointer passed 00159 InitStats(&mpSpectrum->GetMagBuffer()); 00160 00161 mDeltaFreq=double(mpSpectrum->GetSpectralRange())/(mpSpectrum->GetSize()-1); 00162 00163 } 00164 00165 void SpectralDescriptors::ConcreteCompute() 00166 { 00167 if (HasMean()) 00168 SetMean(mpStats->GetMean()); 00169 if (HasGeometricMean()) 00170 { 00171 CLAM_ASSERT( mpSpectrum->GetScale() == CLAM::EScale::eLinear, 00172 "The Geometric Mean, as implemented in CLAM, can only" 00173 " be computed over Linear Spectral Power distirbutions"); 00174 SetGeometricMean(mpStats->GetGeometricMean()); 00175 } 00176 if (HasEnergy()) 00177 SetEnergy(mpStats->GetEnergy()); 00178 if (HasCentroid()) 00179 SetCentroid(mpStats->GetCentroid()*mDeltaFreq); 00180 if(HasMoment2()) 00181 SetMoment2(mpStats->GetMoment(SecondOrder)); 00182 if(HasMoment3()) 00183 SetMoment3(mpStats->GetMoment(ThirdOrder)); 00184 if(HasMoment4()) 00185 SetMoment4(mpStats->GetMoment(FourthOrder)); 00186 if(HasMoment5()) 00187 SetMoment5(mpStats->GetMoment(FifthOrder)); 00188 if(HasMoment6()) 00189 SetMoment6(mpStats->GetMoment((O<6>*)(0))); 00190 if (HasSpread()) 00191 SetSpread(mpStats->GetSpread()*mDeltaFreq*mDeltaFreq); 00192 if(HasMagnitudeSkewness()) 00193 SetMagnitudeSkewness(mpStats->GetSkew()); 00194 if(HasMagnitudeKurtosis()) 00195 SetMagnitudeKurtosis(mpStats->GetKurtosis()); 00196 if(HasFlatness()) 00197 SetFlatness(ComputeSpectralFlatness()); 00198 if(HasHighFrequencyContent()) 00199 SetHighFrequencyContent(ComputeHighFrequencyContent()); 00200 if(HasMaxMagFreq()) 00201 SetMaxMagFreq(ComputeMaxMagFreq()); 00202 if(HasLowFreqEnergyRelation()) 00203 SetLowFreqEnergyRelation(ComputeLowFreqEnergyRelation()); 00204 if(HasRolloff()) 00205 SetRolloff(ComputeRolloff()); 00206 if(HasSlope()) 00207 SetSlope(mpStats->GetSlope()/mDeltaFreq); 00208 } 00209 00210 00211 /*this has been mostly copied and pasted from cuidado and should be checked and some of 00212 it promoted into basicOps*/ 00213 TData SpectralDescriptors::ComputeSpectralFlatness() 00214 { 00215 return mpStats->GetFlatness(); 00216 } 00217 00218 /*this has been mostly copied and pasted from cuidado and should be checked and some of 00219 it promoted into basicOps*/ 00220 TData SpectralDescriptors::ComputeHighFrequencyContent() 00221 { 00222 const DataArray & mag = mpSpectrum->GetMagBuffer(); 00223 const TSize size=mpSpectrum->GetSize(); 00224 double temp = 0.0; 00225 for (int i=1;i<size;i++) 00226 temp += mag[i]*mag[i]*i; 00227 return temp; 00228 /* 00229 return WeightedPoweredSum<2>()(mpSpectrum->GetMagBuffer()); 00230 */ 00231 } 00232 00241 TData SpectralDescriptors::ComputeMaxMagFreq() 00242 { 00243 // Zero is not enough for spectrums in dB's 00244 TData max = -1000.0; 00245 TIndex index = -1; 00246 00247 const DataArray& data=mpSpectrum->GetMagBuffer(); 00248 const unsigned size=mpSpectrum->GetSize(); 00249 for(unsigned i=0; i<size; i++) 00250 if(data[i] > max ) 00251 { 00252 max = data[i]; 00253 index = i; 00254 } 00255 00256 // Convert from index to frequency value in Hz 00257 return (TData) index * mDeltaFreq; 00258 } 00259 00260 /*this has been mostly copied and pasted from cuidado and should be checked and some of 00261 it promoted into basicOps*/ 00262 TData SpectralDescriptors::ComputeLowFreqEnergyRelation() 00263 { 00264 // Energy(0-100 Hz) / Total Energy 00265 TIndex index = Round(100.0/mDeltaFreq); 00266 const DataArray & magnitudeBuffer = mpSpectrum->GetMagBuffer(); 00267 const DataArray data(const_cast<TData*>(magnitudeBuffer.GetPtr()), index); 00268 00269 Energy energyComputer; 00270 TData totalEnergy = mpStats->GetEnergy(); 00271 if (totalEnergy < 10e-4) totalEnergy=10e-4; 00272 00273 TData result=(energyComputer(data)/totalEnergy ); 00274 return result; 00275 } 00276 00277 TData SpectralDescriptors::ComputeRolloff() 00278 { 00279 DataArray& mags = mpSpectrum->GetMagBuffer(); 00280 TSize magsSize = mpSpectrum->GetSize(); 00281 00282 TData eThreshold = 0.85 * mpStats->GetEnergy(); 00283 TData cumEnergy = 0; 00284 for (TIndex i=0; i<magsSize; i++) 00285 { 00286 cumEnergy += mags[i]*mags[i]; 00287 if (cumEnergy <= eThreshold) continue; 00288 return i * mDeltaFreq; 00289 } 00290 return 0.0; 00291 } 00292 00293 00294 SpectralDescriptors operator * (const SpectralDescriptors& a,TData mult) 00295 { 00296 SpectralDescriptors tmpD(a); 00297 if(a.HasMean()) 00298 tmpD.SetMean(a.GetMean()*mult); 00299 if(a.HasGeometricMean()) 00300 tmpD.SetGeometricMean(a.GetGeometricMean()*mult); 00301 if(a.HasEnergy()) 00302 tmpD.SetEnergy(a.GetEnergy()*mult); 00303 if(a.HasCentroid()) 00304 tmpD.SetCentroid(a.GetCentroid()*mult); 00305 if(a.HasMoment2()) 00306 tmpD.SetMoment2(a.GetMoment2()*mult); 00307 if(a.HasMoment3()) 00308 tmpD.SetMoment3(a.GetMoment3()*mult); 00309 if(a.HasMoment4()) 00310 tmpD.SetMoment4(a.GetMoment4()*mult); 00311 if(a.HasMoment5()) 00312 tmpD.SetMoment5(a.GetMoment5()*mult); 00313 if(a.HasMoment6()) 00314 tmpD.SetMoment6(a.GetMoment6()*mult); 00315 if(a.HasFlatness()) 00316 tmpD.SetFlatness(a.GetFlatness()*mult); 00317 if(a.HasMagnitudeKurtosis()) 00318 tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()*mult); 00319 if(a.HasMaxMagFreq()) 00320 tmpD.SetMaxMagFreq(a.GetMaxMagFreq()*mult); 00321 if(a.HasLowFreqEnergyRelation()) 00322 tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()*mult); 00323 if(a.HasSpread()) 00324 tmpD.SetSpread(a.GetSpread()*mult); 00325 if(a.HasMagnitudeSkewness()) 00326 tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()*mult); 00327 if(a.HasRolloff()) 00328 tmpD.SetRolloff(a.GetRolloff()*mult); 00329 if(a.HasSlope()) 00330 tmpD.SetSlope(a.GetSlope()*mult); 00331 if(a.HasHighFrequencyContent()) 00332 tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()*mult); 00333 if(a.HasBandDescriptors()) 00334 //todo!!! We are not multiplying because we would need the operator implemented in the array 00335 tmpD.SetBandDescriptors(a.GetBandDescriptors()); 00336 if(a.HasMFCC()) 00337 //todo!!! We are not multiplying because we would need the operator implemented in the array 00338 tmpD.SetMFCC(a.GetMFCC()); 00339 if(a.HasPCP()) 00340 tmpD.SetPCP(Multiply(mult,a.GetPCP())); 00341 00342 return tmpD; 00343 } 00344 00345 SpectralDescriptors operator * (const SpectralDescriptors& a,const SpectralDescriptors& b) 00346 { 00347 SpectralDescriptors tmpD; 00348 if(a.HasMean() && b.HasMean() ) 00349 { 00350 tmpD.AddMean(); 00351 tmpD.UpdateData(); 00352 tmpD.SetMean(a.GetMean()*b.GetMean()); 00353 } 00354 if(a.HasGeometricMean() && b.HasGeometricMean() ) 00355 { 00356 tmpD.AddGeometricMean(); 00357 tmpD.UpdateData(); 00358 tmpD.SetGeometricMean(a.GetGeometricMean()*b.GetGeometricMean()); 00359 } 00360 if(a.HasEnergy() && b.HasEnergy() ) 00361 { 00362 tmpD.AddEnergy(); 00363 tmpD.UpdateData(); 00364 tmpD.SetEnergy(a.GetEnergy()*b.GetEnergy()); 00365 } 00366 if(a.HasCentroid() && b.HasCentroid() ) 00367 { 00368 tmpD.AddCentroid(); 00369 tmpD.UpdateData(); 00370 tmpD.SetCentroid(a.GetCentroid()*b.GetCentroid()); 00371 } 00372 if(a.HasMoment2() && b.HasMoment2() ) 00373 { 00374 tmpD.AddMoment2(); 00375 tmpD.UpdateData(); 00376 tmpD.SetMoment2(a.GetMoment2()*b.GetMoment2()); 00377 } 00378 if(a.HasMoment3() && b.HasMoment3() ) 00379 { 00380 tmpD.AddMoment3(); 00381 tmpD.UpdateData(); 00382 tmpD.SetMoment3(a.GetMoment3()*b.GetMoment3()); 00383 } 00384 if(a.HasMoment4() && b.HasMoment4() ) 00385 { 00386 tmpD.AddMoment4(); 00387 tmpD.UpdateData(); 00388 tmpD.SetMoment4(a.GetMoment4()*b.HasMoment4()); 00389 } 00390 if(a.HasMoment5() && b.HasMoment5()) 00391 { 00392 tmpD.AddMoment5(); 00393 tmpD.UpdateData(); 00394 tmpD.SetMoment5(a.GetMoment5()*b.GetMoment5()); 00395 } 00396 if(a.HasMoment6() && b.HasMoment6() ) 00397 { 00398 tmpD.AddMoment6(); 00399 tmpD.UpdateData(); 00400 tmpD.SetMoment6(a.GetMoment6()*b.GetMoment6()); 00401 } 00402 if(a.HasFlatness() && b.HasFlatness() ) 00403 { 00404 tmpD.AddFlatness(); 00405 tmpD.UpdateData(); 00406 tmpD.SetFlatness(a.GetFlatness()*b.GetFlatness()); 00407 } 00408 if(a.HasMagnitudeKurtosis() && b.HasMagnitudeKurtosis() ) 00409 { 00410 tmpD.AddMagnitudeKurtosis(); 00411 tmpD.UpdateData(); 00412 tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()*b.GetMagnitudeKurtosis()); 00413 } 00414 if(a.HasMaxMagFreq() && b.HasMaxMagFreq() ) 00415 { 00416 tmpD.AddMaxMagFreq(); 00417 tmpD.UpdateData(); 00418 tmpD.SetMaxMagFreq(a.GetMaxMagFreq()*b.GetMaxMagFreq()); 00419 } 00420 if(a.HasLowFreqEnergyRelation() && b.HasLowFreqEnergyRelation() ) 00421 { 00422 tmpD.AddLowFreqEnergyRelation(); 00423 tmpD.UpdateData(); 00424 tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()*b.GetLowFreqEnergyRelation()); 00425 } 00426 if(a.HasSpread() && b.HasSpread() ) 00427 { 00428 tmpD.AddSpread(); 00429 tmpD.UpdateData(); 00430 tmpD.SetSpread(a.GetSpread()*b.GetSpread()); 00431 } 00432 if(a.HasMagnitudeSkewness() && b.HasMagnitudeSkewness() ) 00433 { 00434 tmpD.AddMagnitudeSkewness(); 00435 tmpD.UpdateData(); 00436 tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()*b.GetMagnitudeSkewness()); 00437 } 00438 if(a.HasRolloff() && b.HasRolloff() ) 00439 { 00440 tmpD.AddRolloff(); 00441 tmpD.UpdateData(); 00442 tmpD.SetRolloff(a.GetRolloff()*b.GetRolloff()); 00443 } 00444 if(a.HasSlope() && b.HasSlope() ) 00445 { 00446 tmpD.AddSlope(); 00447 tmpD.UpdateData(); 00448 tmpD.SetSlope(a.GetSlope()*b.GetSlope()); 00449 } 00450 if(a.HasHighFrequencyContent() && b.HasHighFrequencyContent() ) 00451 { 00452 tmpD.AddHighFrequencyContent(); 00453 tmpD.UpdateData(); 00454 tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()*b.GetHighFrequencyContent()); 00455 } 00456 if(a.HasBandDescriptors() && b.HasBandDescriptors() ) 00457 { 00458 tmpD.AddBandDescriptors(); 00459 tmpD.UpdateData(); 00460 //todo!!! We are not multiplying because we would need the operator implemented in the array 00461 tmpD.SetBandDescriptors(a.GetBandDescriptors() ); 00462 } 00463 if(a.HasMFCC() && b.HasMFCC() ) 00464 { 00465 tmpD.AddMFCC(); 00466 tmpD.UpdateData(); 00467 //todo!!! We are not multiplying because we would need the operator implemented in the array 00468 tmpD.SetMFCC(a.GetMFCC() ); 00469 } 00470 if(a.HasPCP() && b.HasPCP() ) 00471 { 00472 tmpD.AddPCP(); 00473 tmpD.UpdateData(); 00474 tmpD.SetPCP(Multiply(a.GetPCP(),b.GetPCP())); 00475 } 00476 return tmpD; 00477 } 00478 00479 00480 SpectralDescriptors operator / (const SpectralDescriptors& a,TData div) 00481 { 00482 return a*(1/div); 00483 } 00484 00485 SpectralDescriptors operator + (const SpectralDescriptors& a, const SpectralDescriptors& b) 00486 { 00487 SpectralDescriptors tmpD; 00488 if(a.HasMean() && b.HasMean() ) 00489 { 00490 tmpD.AddMean(); 00491 tmpD.UpdateData(); 00492 tmpD.SetMean(a.GetMean()+b.GetMean()); 00493 } 00494 if(a.HasGeometricMean() && b.HasGeometricMean() ) 00495 { 00496 tmpD.AddGeometricMean(); 00497 tmpD.UpdateData(); 00498 tmpD.SetGeometricMean(a.GetGeometricMean()+b.GetGeometricMean()); 00499 } 00500 if(a.HasEnergy() && b.HasEnergy() ) 00501 { 00502 tmpD.AddEnergy(); 00503 tmpD.UpdateData(); 00504 tmpD.SetEnergy(a.GetEnergy()+b.GetEnergy()); 00505 } 00506 if(a.HasCentroid() && b.HasCentroid() ) 00507 { 00508 tmpD.AddCentroid(); 00509 tmpD.UpdateData(); 00510 tmpD.SetCentroid(a.GetCentroid()+b.GetCentroid()); 00511 } 00512 if(a.HasMoment2() && b.HasMoment2() ) 00513 { 00514 tmpD.AddMoment2(); 00515 tmpD.UpdateData(); 00516 tmpD.SetMoment2(a.GetMoment2()+b.GetMoment2()); 00517 } 00518 if(a.HasMoment3() && b.HasMoment3() ) 00519 { 00520 tmpD.AddMoment3(); 00521 tmpD.UpdateData(); 00522 tmpD.SetMoment3(a.GetMoment3()+b.GetMoment3()); 00523 } 00524 if(a.HasMoment4() && b.HasMoment4() ) 00525 { 00526 tmpD.AddMoment4(); 00527 tmpD.UpdateData(); 00528 tmpD.SetMoment4(a.GetMoment4()+b.HasMoment4()); 00529 } 00530 if(a.HasMoment5() && b.HasMoment5()) 00531 { 00532 tmpD.AddMoment5(); 00533 tmpD.UpdateData(); 00534 tmpD.SetMoment5(a.GetMoment5()+b.GetMoment5()); 00535 } 00536 if(a.HasMoment6() && b.HasMoment6() ) 00537 { 00538 tmpD.AddMoment6(); 00539 tmpD.UpdateData(); 00540 tmpD.SetMoment6(a.GetMoment6()+b.GetMoment6()); 00541 } 00542 if(a.HasFlatness() && b.HasFlatness() ) 00543 { 00544 tmpD.AddFlatness(); 00545 tmpD.UpdateData(); 00546 tmpD.SetFlatness(a.GetFlatness()+b.GetFlatness()); 00547 } 00548 if(a.HasMagnitudeKurtosis() && b.HasMagnitudeKurtosis() ) 00549 { 00550 tmpD.AddMagnitudeKurtosis(); 00551 tmpD.UpdateData(); 00552 tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()+b.GetMagnitudeKurtosis()); 00553 } 00554 if(a.HasMaxMagFreq() && b.HasMaxMagFreq() ) 00555 { 00556 tmpD.AddMaxMagFreq(); 00557 tmpD.UpdateData(); 00558 tmpD.SetMaxMagFreq(a.GetMaxMagFreq()+b.GetMaxMagFreq()); 00559 } 00560 if(a.HasLowFreqEnergyRelation() && b.HasLowFreqEnergyRelation() ) 00561 { 00562 tmpD.AddLowFreqEnergyRelation(); 00563 tmpD.UpdateData(); 00564 tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()+b.GetLowFreqEnergyRelation()); 00565 } 00566 if(a.HasSpread() && b.HasSpread() ) 00567 { 00568 tmpD.AddSpread(); 00569 tmpD.UpdateData(); 00570 tmpD.SetSpread(a.GetSpread()+b.GetSpread()); 00571 } 00572 if(a.HasMagnitudeSkewness() && b.HasMagnitudeSkewness() ) 00573 { 00574 tmpD.AddMagnitudeSkewness(); 00575 tmpD.UpdateData(); 00576 tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()+b.GetMagnitudeSkewness()); 00577 } 00578 if(a.HasRolloff() && b.HasRolloff() ) 00579 { 00580 tmpD.AddRolloff(); 00581 tmpD.UpdateData(); 00582 tmpD.SetRolloff(a.GetRolloff()+b.GetRolloff()); 00583 } 00584 if(a.HasSlope() && b.HasSlope() ) 00585 { 00586 tmpD.AddSlope(); 00587 tmpD.UpdateData(); 00588 tmpD.SetSlope(a.GetSlope()+b.GetSlope()); 00589 } 00590 if(a.HasHighFrequencyContent() && b.HasHighFrequencyContent() ) 00591 { 00592 tmpD.AddHighFrequencyContent(); 00593 tmpD.UpdateData(); 00594 tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()+b.GetHighFrequencyContent()); 00595 } 00596 if(a.HasBandDescriptors() && b.HasBandDescriptors() ) 00597 { 00598 tmpD.AddBandDescriptors(); 00599 tmpD.UpdateData(); 00600 //todo!!! We are not multiplying because we would need the operator implemented in the array 00601 tmpD.SetBandDescriptors(a.GetBandDescriptors() /* + b.GetBandDescriptors()*/ ); 00602 } 00603 if(a.HasMFCC() && b.HasMFCC() ) 00604 { 00605 tmpD.AddMFCC(); 00606 tmpD.UpdateData(); 00607 //todo!!! We are not multiplying because we would need the operator implemented in the array 00608 tmpD.SetMFCC(a.GetMFCC() /* + b.GetMFCC() */); 00609 } 00610 if(a.HasPCP() && b.HasPCP() ) 00611 { 00612 tmpD.AddPCP(); 00613 tmpD.UpdateData(); 00614 tmpD.SetPCP(Add(a.GetPCP(),b.GetPCP())); 00615 } 00616 00617 return tmpD; 00618 00619 } 00620 00621 00622 SpectralDescriptors operator * (TData mult,const SpectralDescriptors& a) 00623 { 00624 return a*mult; 00625 } 00626 00627 00628 }; 00629