CLAM-Development  1.4.0
SpectralDescriptors.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "SpectralDescriptors.hxx"
23 #include "Spectrum.hxx"
24 #include "Array.hxx"
25 #include <algorithm>
26 
27 namespace CLAM{
28 
30  TIndex i;
31  TSize sizea=a.Size();
32  TSize sizeb=b.Size();
33  TSize size;
34  DataArray result;
35 
36  // One has size==0 (optimized with respect to the following case?)
37  if (sizea==0) {
38  result=b;
39  return result;
40  }
41  if (sizeb==0) {
42  result=a;
43  return result;
44  }
45 
46  // Different sizes
47  if(sizea != sizeb) {
48  if (sizea < sizeb) {
49  size=sizeb;
50  result.Resize(size);
51  result.SetSize(size);
52  for (i=0; i<sizea; i++)
53  result[i]=a[i]+b[i];
54  for (i=sizea; i<sizeb; i++)
55  result[i]=b[i];
56  return result;
57  }
58  else { // sizea>sizeb
59  size=sizea;
60  result.Resize(size);
61  result.SetSize(size);
62  for (i=0; i<sizeb; i++)
63  result[i]=a[i]+b[i];
64  for (i=sizeb; i<sizea; i++)
65  result[i]=a[i];
66  return result;
67  }
68  }
69  // Equal size
70  size=sizea;
71  result.Resize(size);
72  result.SetSize(size);
73  for (i=0; i<size; i++)
74  result[i]=a[i]+b[i];
75  return result;
76 }
77 
79  TIndex i;
80  TSize size=a.Size();
81  DataArray result;
82  result.Resize(size);
83  result.SetSize(size);
84  for (i=0; i<size; i++)
85  result[i]=factor*a[i];
86  return result;
87 }
88 
89 /* Scalar product of two vectors */
91  TIndex i;
92  TSize size=a.Size();
93  DataArray result;
94  result.Resize(size);
95  result.SetSize(size);
96  for (i=0; i<size; i++)
97  result[i]=a[i]*b[i];
98  return result;
99 }
100 
102 {
103  CLAM_ASSERT(pSpectrum->GetScale()==EScale::eLinear,
104  "Spectral Descriptors require a linear magnitude Spectrum");
105  MandatoryInit();
106  mpSpectrum=pSpectrum;
107 }
108 
110 {
111  MandatoryInit();
112  AddAll();
113  UpdateData();
114  SetMean(initVal);
115  SetGeometricMean(initVal);
116  SetEnergy(initVal);
117  SetCentroid(initVal);
118  SetMoment2(initVal);
119  SetMoment3(initVal);
120  SetMoment4(initVal);
121  SetMoment5(initVal);
122  SetMoment6(initVal);
123  SetSpread(initVal);
124  SetMagnitudeSkewness(initVal);
125  SetMagnitudeKurtosis(initVal);
126  SetFlatness(initVal);
127  SetHighFrequencyContent(initVal);
128  SetMaxMagFreq(initVal);
129  SetLowFreqEnergyRelation(initVal);
130  SetRolloff(initVal);
131  SetSlope(initVal);
132 }
133 
135  mpSpectrum=0;
136  mpStats=0;
137  //Warning: no attributes are added by default, the user is in charge of adding the ones he is interested in
138 }
139 
141 {
142  mpSpectrum=copied.mpSpectrum;
143  mpStats=0;
144 }
145 
147 {
148  return mpSpectrum;
149 }
150 
152 {
153 
154  CLAM_ASSERT(pSpectrum->GetScale()==EScale::eLinear,
155  "Spectral Descriptors require a linear magnitude Spectrum");
156  mpSpectrum=pSpectrum;
157  //TODO: we are asuming Spectrum is in MagBuffer
158  //TODO: it may give problems because pointer passed
159  InitStats(&mpSpectrum->GetMagBuffer());
160 
161  mDeltaFreq=double(mpSpectrum->GetSpectralRange())/(mpSpectrum->GetSize()-1);
162 
163 }
164 
166 {
167  if (HasMean())
168  SetMean(mpStats->GetMean());
169  if (HasGeometricMean())
170  {
171  CLAM_ASSERT( mpSpectrum->GetScale() == CLAM::EScale::eLinear,
172  "The Geometric Mean, as implemented in CLAM, can only"
173  " be computed over Linear Spectral Power distirbutions");
174  SetGeometricMean(mpStats->GetGeometricMean());
175  }
176  if (HasEnergy())
177  SetEnergy(mpStats->GetEnergy());
178  if (HasCentroid())
179  SetCentroid(mpStats->GetCentroid()*mDeltaFreq);
180  if(HasMoment2())
181  SetMoment2(mpStats->GetMoment(SecondOrder));
182  if(HasMoment3())
183  SetMoment3(mpStats->GetMoment(ThirdOrder));
184  if(HasMoment4())
185  SetMoment4(mpStats->GetMoment(FourthOrder));
186  if(HasMoment5())
187  SetMoment5(mpStats->GetMoment(FifthOrder));
188  if(HasMoment6())
189  SetMoment6(mpStats->GetMoment((O<6>*)(0)));
190  if (HasSpread())
191  SetSpread(mpStats->GetSpread()*mDeltaFreq*mDeltaFreq);
192  if(HasMagnitudeSkewness())
193  SetMagnitudeSkewness(mpStats->GetSkew());
194  if(HasMagnitudeKurtosis())
195  SetMagnitudeKurtosis(mpStats->GetKurtosis());
196  if(HasFlatness())
197  SetFlatness(ComputeSpectralFlatness());
198  if(HasHighFrequencyContent())
199  SetHighFrequencyContent(ComputeHighFrequencyContent());
200  if(HasMaxMagFreq())
201  SetMaxMagFreq(ComputeMaxMagFreq());
202  if(HasLowFreqEnergyRelation())
203  SetLowFreqEnergyRelation(ComputeLowFreqEnergyRelation());
204  if(HasRolloff())
205  SetRolloff(ComputeRolloff());
206  if(HasSlope())
207  SetSlope(mpStats->GetSlope()/mDeltaFreq);
208 }
209 
210 
211 /*this has been mostly copied and pasted from cuidado and should be checked and some of
212 it promoted into basicOps*/
214 {
215  return mpStats->GetFlatness();
216 }
217 
218 /*this has been mostly copied and pasted from cuidado and should be checked and some of
219 it promoted into basicOps*/
221 {
222  const DataArray & mag = mpSpectrum->GetMagBuffer();
223  const TSize size=mpSpectrum->GetSize();
224  double temp = 0.0;
225  for (int i=1;i<size;i++)
226  temp += mag[i]*mag[i]*i;
227  return temp;
228  /*
229  return WeightedPoweredSum<2>()(mpSpectrum->GetMagBuffer());
230  */
231 }
232 
242 {
243  // Zero is not enough for spectrums in dB's
244  TData max = -1000.0;
245  TIndex index = -1;
246 
247  const DataArray& data=mpSpectrum->GetMagBuffer();
248  const unsigned size=mpSpectrum->GetSize();
249  for(unsigned i=0; i<size; i++)
250  if(data[i] > max )
251  {
252  max = data[i];
253  index = i;
254  }
255 
256  // Convert from index to frequency value in Hz
257  return (TData) index * mDeltaFreq;
258 }
259 
260 /*this has been mostly copied and pasted from cuidado and should be checked and some of
261 it promoted into basicOps*/
263 {
264  // Energy(0-100 Hz) / Total Energy
265  TIndex index = Round(100.0/mDeltaFreq);
266  const DataArray & magnitudeBuffer = mpSpectrum->GetMagBuffer();
267  const DataArray data(const_cast<TData*>(magnitudeBuffer.GetPtr()), index);
268 
269  Energy energyComputer;
270  TData totalEnergy = mpStats->GetEnergy();
271  if (totalEnergy < 10e-4) totalEnergy=10e-4;
272 
273  TData result=(energyComputer(data)/totalEnergy );
274  return result;
275 }
276 
278 {
279  DataArray& mags = mpSpectrum->GetMagBuffer();
280  TSize magsSize = mpSpectrum->GetSize();
281 
282  TData eThreshold = 0.85 * mpStats->GetEnergy();
283  TData cumEnergy = 0;
284  for (TIndex i=0; i<magsSize; i++)
285  {
286  cumEnergy += mags[i]*mags[i];
287  if (cumEnergy <= eThreshold) continue;
288  return i * mDeltaFreq;
289  }
290  return 0.0;
291 }
292 
293 
295 {
296  SpectralDescriptors tmpD(a);
297  if(a.HasMean())
298  tmpD.SetMean(a.GetMean()*mult);
299  if(a.HasGeometricMean())
300  tmpD.SetGeometricMean(a.GetGeometricMean()*mult);
301  if(a.HasEnergy())
302  tmpD.SetEnergy(a.GetEnergy()*mult);
303  if(a.HasCentroid())
304  tmpD.SetCentroid(a.GetCentroid()*mult);
305  if(a.HasMoment2())
306  tmpD.SetMoment2(a.GetMoment2()*mult);
307  if(a.HasMoment3())
308  tmpD.SetMoment3(a.GetMoment3()*mult);
309  if(a.HasMoment4())
310  tmpD.SetMoment4(a.GetMoment4()*mult);
311  if(a.HasMoment5())
312  tmpD.SetMoment5(a.GetMoment5()*mult);
313  if(a.HasMoment6())
314  tmpD.SetMoment6(a.GetMoment6()*mult);
315  if(a.HasFlatness())
316  tmpD.SetFlatness(a.GetFlatness()*mult);
317  if(a.HasMagnitudeKurtosis())
318  tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()*mult);
319  if(a.HasMaxMagFreq())
320  tmpD.SetMaxMagFreq(a.GetMaxMagFreq()*mult);
321  if(a.HasLowFreqEnergyRelation())
322  tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()*mult);
323  if(a.HasSpread())
324  tmpD.SetSpread(a.GetSpread()*mult);
325  if(a.HasMagnitudeSkewness())
326  tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()*mult);
327  if(a.HasRolloff())
328  tmpD.SetRolloff(a.GetRolloff()*mult);
329  if(a.HasSlope())
330  tmpD.SetSlope(a.GetSlope()*mult);
331  if(a.HasHighFrequencyContent())
332  tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()*mult);
333  if(a.HasBandDescriptors())
334  //todo!!! We are not multiplying because we would need the operator implemented in the array
335  tmpD.SetBandDescriptors(a.GetBandDescriptors());
336  if(a.HasMFCC())
337  //todo!!! We are not multiplying because we would need the operator implemented in the array
338  tmpD.SetMFCC(a.GetMFCC());
339  if(a.HasPCP())
340  tmpD.SetPCP(Multiply(mult,a.GetPCP()));
341 
342  return tmpD;
343 }
344 
346 {
347  SpectralDescriptors tmpD;
348  if(a.HasMean() && b.HasMean() )
349  {
350  tmpD.AddMean();
351  tmpD.UpdateData();
352  tmpD.SetMean(a.GetMean()*b.GetMean());
353  }
354  if(a.HasGeometricMean() && b.HasGeometricMean() )
355  {
356  tmpD.AddGeometricMean();
357  tmpD.UpdateData();
358  tmpD.SetGeometricMean(a.GetGeometricMean()*b.GetGeometricMean());
359  }
360  if(a.HasEnergy() && b.HasEnergy() )
361  {
362  tmpD.AddEnergy();
363  tmpD.UpdateData();
364  tmpD.SetEnergy(a.GetEnergy()*b.GetEnergy());
365  }
366  if(a.HasCentroid() && b.HasCentroid() )
367  {
368  tmpD.AddCentroid();
369  tmpD.UpdateData();
370  tmpD.SetCentroid(a.GetCentroid()*b.GetCentroid());
371  }
372  if(a.HasMoment2() && b.HasMoment2() )
373  {
374  tmpD.AddMoment2();
375  tmpD.UpdateData();
376  tmpD.SetMoment2(a.GetMoment2()*b.GetMoment2());
377  }
378  if(a.HasMoment3() && b.HasMoment3() )
379  {
380  tmpD.AddMoment3();
381  tmpD.UpdateData();
382  tmpD.SetMoment3(a.GetMoment3()*b.GetMoment3());
383  }
384  if(a.HasMoment4() && b.HasMoment4() )
385  {
386  tmpD.AddMoment4();
387  tmpD.UpdateData();
388  tmpD.SetMoment4(a.GetMoment4()*b.HasMoment4());
389  }
390  if(a.HasMoment5() && b.HasMoment5())
391  {
392  tmpD.AddMoment5();
393  tmpD.UpdateData();
394  tmpD.SetMoment5(a.GetMoment5()*b.GetMoment5());
395  }
396  if(a.HasMoment6() && b.HasMoment6() )
397  {
398  tmpD.AddMoment6();
399  tmpD.UpdateData();
400  tmpD.SetMoment6(a.GetMoment6()*b.GetMoment6());
401  }
402  if(a.HasFlatness() && b.HasFlatness() )
403  {
404  tmpD.AddFlatness();
405  tmpD.UpdateData();
406  tmpD.SetFlatness(a.GetFlatness()*b.GetFlatness());
407  }
408  if(a.HasMagnitudeKurtosis() && b.HasMagnitudeKurtosis() )
409  {
410  tmpD.AddMagnitudeKurtosis();
411  tmpD.UpdateData();
412  tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()*b.GetMagnitudeKurtosis());
413  }
414  if(a.HasMaxMagFreq() && b.HasMaxMagFreq() )
415  {
416  tmpD.AddMaxMagFreq();
417  tmpD.UpdateData();
418  tmpD.SetMaxMagFreq(a.GetMaxMagFreq()*b.GetMaxMagFreq());
419  }
420  if(a.HasLowFreqEnergyRelation() && b.HasLowFreqEnergyRelation() )
421  {
422  tmpD.AddLowFreqEnergyRelation();
423  tmpD.UpdateData();
424  tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()*b.GetLowFreqEnergyRelation());
425  }
426  if(a.HasSpread() && b.HasSpread() )
427  {
428  tmpD.AddSpread();
429  tmpD.UpdateData();
430  tmpD.SetSpread(a.GetSpread()*b.GetSpread());
431  }
432  if(a.HasMagnitudeSkewness() && b.HasMagnitudeSkewness() )
433  {
434  tmpD.AddMagnitudeSkewness();
435  tmpD.UpdateData();
436  tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()*b.GetMagnitudeSkewness());
437  }
438  if(a.HasRolloff() && b.HasRolloff() )
439  {
440  tmpD.AddRolloff();
441  tmpD.UpdateData();
442  tmpD.SetRolloff(a.GetRolloff()*b.GetRolloff());
443  }
444  if(a.HasSlope() && b.HasSlope() )
445  {
446  tmpD.AddSlope();
447  tmpD.UpdateData();
448  tmpD.SetSlope(a.GetSlope()*b.GetSlope());
449  }
450  if(a.HasHighFrequencyContent() && b.HasHighFrequencyContent() )
451  {
452  tmpD.AddHighFrequencyContent();
453  tmpD.UpdateData();
454  tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()*b.GetHighFrequencyContent());
455  }
456  if(a.HasBandDescriptors() && b.HasBandDescriptors() )
457  {
458  tmpD.AddBandDescriptors();
459  tmpD.UpdateData();
460  //todo!!! We are not multiplying because we would need the operator implemented in the array
461  tmpD.SetBandDescriptors(a.GetBandDescriptors() );
462  }
463  if(a.HasMFCC() && b.HasMFCC() )
464  {
465  tmpD.AddMFCC();
466  tmpD.UpdateData();
467  //todo!!! We are not multiplying because we would need the operator implemented in the array
468  tmpD.SetMFCC(a.GetMFCC() );
469  }
470  if(a.HasPCP() && b.HasPCP() )
471  {
472  tmpD.AddPCP();
473  tmpD.UpdateData();
474  tmpD.SetPCP(Multiply(a.GetPCP(),b.GetPCP()));
475  }
476  return tmpD;
477 }
478 
479 
481 {
482  return a*(1/div);
483 }
484 
486 {
487  SpectralDescriptors tmpD;
488  if(a.HasMean() && b.HasMean() )
489  {
490  tmpD.AddMean();
491  tmpD.UpdateData();
492  tmpD.SetMean(a.GetMean()+b.GetMean());
493  }
494  if(a.HasGeometricMean() && b.HasGeometricMean() )
495  {
496  tmpD.AddGeometricMean();
497  tmpD.UpdateData();
498  tmpD.SetGeometricMean(a.GetGeometricMean()+b.GetGeometricMean());
499  }
500  if(a.HasEnergy() && b.HasEnergy() )
501  {
502  tmpD.AddEnergy();
503  tmpD.UpdateData();
504  tmpD.SetEnergy(a.GetEnergy()+b.GetEnergy());
505  }
506  if(a.HasCentroid() && b.HasCentroid() )
507  {
508  tmpD.AddCentroid();
509  tmpD.UpdateData();
510  tmpD.SetCentroid(a.GetCentroid()+b.GetCentroid());
511  }
512  if(a.HasMoment2() && b.HasMoment2() )
513  {
514  tmpD.AddMoment2();
515  tmpD.UpdateData();
516  tmpD.SetMoment2(a.GetMoment2()+b.GetMoment2());
517  }
518  if(a.HasMoment3() && b.HasMoment3() )
519  {
520  tmpD.AddMoment3();
521  tmpD.UpdateData();
522  tmpD.SetMoment3(a.GetMoment3()+b.GetMoment3());
523  }
524  if(a.HasMoment4() && b.HasMoment4() )
525  {
526  tmpD.AddMoment4();
527  tmpD.UpdateData();
528  tmpD.SetMoment4(a.GetMoment4()+b.HasMoment4());
529  }
530  if(a.HasMoment5() && b.HasMoment5())
531  {
532  tmpD.AddMoment5();
533  tmpD.UpdateData();
534  tmpD.SetMoment5(a.GetMoment5()+b.GetMoment5());
535  }
536  if(a.HasMoment6() && b.HasMoment6() )
537  {
538  tmpD.AddMoment6();
539  tmpD.UpdateData();
540  tmpD.SetMoment6(a.GetMoment6()+b.GetMoment6());
541  }
542  if(a.HasFlatness() && b.HasFlatness() )
543  {
544  tmpD.AddFlatness();
545  tmpD.UpdateData();
546  tmpD.SetFlatness(a.GetFlatness()+b.GetFlatness());
547  }
548  if(a.HasMagnitudeKurtosis() && b.HasMagnitudeKurtosis() )
549  {
550  tmpD.AddMagnitudeKurtosis();
551  tmpD.UpdateData();
552  tmpD.SetMagnitudeKurtosis(a.GetMagnitudeKurtosis()+b.GetMagnitudeKurtosis());
553  }
554  if(a.HasMaxMagFreq() && b.HasMaxMagFreq() )
555  {
556  tmpD.AddMaxMagFreq();
557  tmpD.UpdateData();
558  tmpD.SetMaxMagFreq(a.GetMaxMagFreq()+b.GetMaxMagFreq());
559  }
560  if(a.HasLowFreqEnergyRelation() && b.HasLowFreqEnergyRelation() )
561  {
562  tmpD.AddLowFreqEnergyRelation();
563  tmpD.UpdateData();
564  tmpD.SetLowFreqEnergyRelation(a.GetLowFreqEnergyRelation()+b.GetLowFreqEnergyRelation());
565  }
566  if(a.HasSpread() && b.HasSpread() )
567  {
568  tmpD.AddSpread();
569  tmpD.UpdateData();
570  tmpD.SetSpread(a.GetSpread()+b.GetSpread());
571  }
572  if(a.HasMagnitudeSkewness() && b.HasMagnitudeSkewness() )
573  {
574  tmpD.AddMagnitudeSkewness();
575  tmpD.UpdateData();
576  tmpD.SetMagnitudeSkewness(a.GetMagnitudeSkewness()+b.GetMagnitudeSkewness());
577  }
578  if(a.HasRolloff() && b.HasRolloff() )
579  {
580  tmpD.AddRolloff();
581  tmpD.UpdateData();
582  tmpD.SetRolloff(a.GetRolloff()+b.GetRolloff());
583  }
584  if(a.HasSlope() && b.HasSlope() )
585  {
586  tmpD.AddSlope();
587  tmpD.UpdateData();
588  tmpD.SetSlope(a.GetSlope()+b.GetSlope());
589  }
590  if(a.HasHighFrequencyContent() && b.HasHighFrequencyContent() )
591  {
592  tmpD.AddHighFrequencyContent();
593  tmpD.UpdateData();
594  tmpD.SetHighFrequencyContent(a.GetHighFrequencyContent()+b.GetHighFrequencyContent());
595  }
596  if(a.HasBandDescriptors() && b.HasBandDescriptors() )
597  {
598  tmpD.AddBandDescriptors();
599  tmpD.UpdateData();
600  //todo!!! We are not multiplying because we would need the operator implemented in the array
601  tmpD.SetBandDescriptors(a.GetBandDescriptors() /* + b.GetBandDescriptors()*/ );
602  }
603  if(a.HasMFCC() && b.HasMFCC() )
604  {
605  tmpD.AddMFCC();
606  tmpD.UpdateData();
607  //todo!!! We are not multiplying because we would need the operator implemented in the array
608  tmpD.SetMFCC(a.GetMFCC() /* + b.GetMFCC() */);
609  }
610  if(a.HasPCP() && b.HasPCP() )
611  {
612  tmpD.AddPCP();
613  tmpD.UpdateData();
614  tmpD.SetPCP(Add(a.GetPCP(),b.GetPCP()));
615  }
616 
617  return tmpD;
618 
619 }
620 
621 
623 {
624  return a*mult;
625 }
626 
627 
628 };
629