CLAM-Development  1.4.0
Segmentator.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 "Segmentator.hxx"
23 #include "Point.hxx"
24 #include "Segment.hxx"
25 #include <iostream>
26 #include "SegmentDescriptors.hxx"
27 
28 
29 namespace CLAM
30 {
31  class SegmentBoundaries
32  {
33  public:
35 
36  SegmentBoundaries(int size):mArray(size)
37  {
38  }
39  };
40 }
41 
42 using namespace CLAM;
43 
47 
48 std::ostream& operator << (std::ostream& myStream, const TDescriptorsParams& a)
49 {
50  switch (a.id)
51  {
52  case SpectralMeanId:
53  {
54  myStream << "SpectralMean";
55  break;
56  }
58  {
59  myStream << "SpectralGeometricMean";
60  break;
61  }
62  case SpectralEnergyId:
63  {
64  myStream << "SpectralEnergy";
65  break;
66  }
67  case SpectralCentroidId :
68  {
69  myStream << "SpectralCentroid";
70  break;
71  }
72  case SpectralMoment2Id:
73  {
74  myStream << "SpectralMoment2";
75  break;
76  }
77  case SpectralMoment3Id:
78  {
79  myStream << "SpectralMoment3";
80  break;
81  }
82  case SpectralMoment4Id:
83  {
84  myStream << "SpectralMoment4";
85  break;
86  }
87  case SpectralMoment5Id:
88  {
89  myStream << "SpectralMoment5";
90  break;
91  }
92  case SpectralMoment6Id:
93  {
94  myStream << "SpectralMoment6";
95  break;
96  }
97  case SpectralFlatnessId :
98  {
99  myStream << "SpectralFlatness";
100  break;
101  }
102  case SpectralKurtosisId :
103  {
104  myStream << "SpectralKurtosis";
105  break;
106  }
107  case FundamentalId :
108  {
109  myStream << "Fundamental";
110  break;
111  }
112  default:
113  {
114  myStream << "UnknownDescriptor";
115  break;
116  }
117  }
118  myStream << "threshold=";
119  myStream << a.threshold;
120  myStream << " ";
121  myStream << "percentil=";
122  myStream << a.percentil;
123  return myStream;
124 }
125 
126 std::istream& operator >> (std::istream& myStream, const TDescriptorsParams& a)
127 {
128  CLAM_ASSERT(false, "TDescriptorParams extractor operator is not implemented");
129  return myStream;
130 }
131 
132 
134 {
135  //AddAll();
136  AddDescriptorsParams();
137  AddMinSegmentLength();
138  UpdateData();
139  Array<TDescriptorsParams> tmpArray(0);
140  SetDescriptorsParams(tmpArray);
141  SearchArray<TDescriptorsParams> tmpSearch(GetDescriptorsParams());
142  SetDescriptorsSearch(tmpSearch);
143 
144  // Default values
145  SetMinSegmentLength(0);
146 };
147 
149 {
150  TIndex position;
151  if(GetDescriptorsParams().Size()==0)
152  GetDescriptorsParams().AddElem(descParams);
153  else if ((position=GetDescriptorsSearch().Find(descParams))==-1)
154  {
155  if(descParams<GetDescriptorsParams()[0])
156  GetDescriptorsParams().InsertElem(0,descParams);
157  else
158  GetDescriptorsParams().AddElem(descParams);
159  }
160  else
161  GetDescriptorsParams().InsertElem(position,descParams);
162 }
163 
164 /*false if descriptor is not found, true if it is*/
166 {
167  int pos;
168  if((pos=GetDescriptorsSearch().Find(descParams))!=-1)
169  {
170  descParams.percentil=GetDescriptorsParams()[pos].percentil;
171  descParams.threshold=GetDescriptorsParams()[pos].threshold;
172  return true;
173  }
174  return false;
175 }
176 
178  GetDescriptorsParams().Init();
179 }
180 
184 
186 {
188 }
189 
191 {
192  Configure(c);
193 }
194 
196 {
197 }
198 
199 bool Segmentator::ConcreteConfigure(const ProcessingConfig& c)
200 {
202  return true;
203 }
204 
206 {
207  CLAM_DEBUG_ASSERT(IsRunning(), "Segmentator: Do(): Not in execution mode");
208 
209  CLAM_ASSERT(false, "Segmentator: Do(): Supervised mode not implemented");
210 
211  return false;
212 }
213 
214 
215 bool Segmentator::Do(Segment& originalSegment,SegmentDescriptors& descriptors)
216 {
217  int nFrames=originalSegment.GetnFrames();
218  Matrix descriptorsValues(mConfig.GetDescriptorsParams().Size(),nFrames);
219  UnwrapDescriptors(originalSegment, descriptors,descriptorsValues);
220  Algorithm(originalSegment,descriptorsValues);
221  return true;
222 }
223 
224 
225 void Segmentator::UnwrapDescriptors(const Segment& originalSegment, SegmentDescriptors& descriptors,Matrix& descriptorsValues)
226 {
227  int nFrames=originalSegment.GetnFrames();
228  int nDescriptors=mConfig.GetDescriptorsParams().Size();
229  for(int i=0;i<nFrames;i++)
230  {
231 /*This looks ugly but right now is the only way to deal with it*/
232  int z=0;
233  TData value;
234  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMeanId)
235  {
236  value=descriptors.GetFrameD(i).GetSpectrumD().GetMean();
237  if(value>mConfig.GetDescriptorsParams()[z].threshold)
238  descriptorsValues.SetAt(z,i,value);
239  else descriptorsValues.SetAt(z,i,0);
240  z++;
241  }
242  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralGeometricMeanId )
243  {
244  value=descriptors.GetFrameD(i).GetSpectrumD().GetGeometricMean();
245  if(value>mConfig.GetDescriptorsParams()[z].threshold)
246  descriptorsValues.SetAt(z,i,value);
247  else descriptorsValues.SetAt(z,i,0);
248  z++;
249  }
250  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralEnergyId)
251  {
252  value=descriptors.GetFrameD(i).GetSpectrumD().GetEnergy();
253  if(value>mConfig.GetDescriptorsParams()[z].threshold)
254  descriptorsValues.SetAt(z,i,value);
255  else descriptorsValues.SetAt(z,i,0);
256  z++;
257  }
258  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralCentroidId )
259  {
260  value=descriptors.GetFrameD(i).GetSpectrumD().GetCentroid();
261  if(value>mConfig.GetDescriptorsParams()[z].threshold)
262  descriptorsValues.SetAt(z,i,value);
263  else descriptorsValues.SetAt(z,i,0);
264  z++;
265  }
266  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMoment2Id)
267  {
268  value=descriptors.GetFrameD(i).GetSpectrumD().GetMoment2();
269  if(value>mConfig.GetDescriptorsParams()[z].threshold)
270  descriptorsValues.SetAt(z,i,value);
271  else descriptorsValues.SetAt(z,i,0);
272  z++;
273  }
274  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMoment3Id)
275  {
276  value=descriptors.GetFrameD(i).GetSpectrumD().GetMoment3();
277  if(value>mConfig.GetDescriptorsParams()[z].threshold)
278  descriptorsValues.SetAt(z,i,value);
279  else descriptorsValues.SetAt(z,i,0);
280  z++;
281  }
282  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMoment4Id)
283  {
284  value=descriptors.GetFrameD(i).GetSpectrumD().GetMoment4();
285  if(value>mConfig.GetDescriptorsParams()[z].threshold)
286  descriptorsValues.SetAt(z,i,value);
287  else descriptorsValues.SetAt(z,i,0);
288  z++;
289  }
290  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMoment5Id)
291  {
292  value=descriptors.GetFrameD(i).GetSpectrumD().GetMoment5();
293  if(value>mConfig.GetDescriptorsParams()[z].threshold)
294  descriptorsValues.SetAt(z,i,value);
295  else descriptorsValues.SetAt(z,i,0);
296  z++;
297  }
298  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralMoment6Id)
299  {
300  value=descriptors.GetFrameD(i).GetSpectrumD().GetMoment6();
301  if(value>mConfig.GetDescriptorsParams()[z].threshold)
302  descriptorsValues.SetAt(z,i,value);
303  else descriptorsValues.SetAt(z,i,0);
304  z++;
305  }
306  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralFlatnessId )
307  {
308  value=descriptors.GetFrameD(i).GetSpectrumD().GetFlatness();
309  if(value>mConfig.GetDescriptorsParams()[z].threshold)
310  descriptorsValues.SetAt(z,i,value);
311  else descriptorsValues.SetAt(z,i,0);
312  z++;
313  }
314  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==SpectralKurtosisId )
315  {
316  value=descriptors.GetFrameD(i).GetSpectrumD().GetMagnitudeKurtosis();
317  if(value>mConfig.GetDescriptorsParams()[z].threshold)
318  descriptorsValues.SetAt(z,i,value);
319  else descriptorsValues.SetAt(z,i,0);
320  z++;
321  }
322  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==FundamentalId )
323  {
324  value=originalSegment.GetFrame(i).GetFundamental().GetFreq();
325  if(value>mConfig.GetDescriptorsParams()[z].threshold)
326  descriptorsValues.SetAt(z,i,value);
327  else descriptorsValues.SetAt(z,i,0);
328  z++;
329  }
330  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==AudioEnergyId)
331  {
332  value=descriptors.GetFrameD(i).GetAudioFrameD().GetEnergy();
333  if(value>mConfig.GetDescriptorsParams()[z].threshold)
334  descriptorsValues.SetAt(z,i,value);
335  else descriptorsValues.SetAt(z,i,0);
336  z++;
337  }
338  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==AudioVarianceId)
339  {
340  value=descriptors.GetFrameD(i).GetAudioFrameD().GetVariance();
341  if(value>mConfig.GetDescriptorsParams()[z].threshold)
342  descriptorsValues.SetAt(z,i,value);
343  else descriptorsValues.SetAt(z,i,0);
344  z++;
345  }
346  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==AudioCentroidId)
347  {
348  value=descriptors.GetFrameD(i).GetAudioFrameD().GetTemporalCentroid();
349  if(value>mConfig.GetDescriptorsParams()[z].threshold)
350  descriptorsValues.SetAt(z,i,value);
351  else descriptorsValues.SetAt(z,i,0);
352  z++;
353  }
354  if(z<nDescriptors&&mConfig.GetDescriptorsParams()[z]==AudioZeroCrossingRateId)
355  {
356  value=descriptors.GetFrameD(i).GetAudioFrameD().GetZeroCrossingRate();
357  if(value>mConfig.GetDescriptorsParams()[z].threshold)
358  descriptorsValues.SetAt(z,i,value);
359  else descriptorsValues.SetAt(z,i,0);
360  z++;
361  }
362  }
363 
364 
365 }
366 
367 
368 void Segmentator::Algorithm(Segment& s,const Matrix& values)
369 {
370 
371  // Segmentation objects
372  // segment boundaries for each parameter
373  int nFrames=s.GetnFrames();
374  int nDescriptors=mConfig.GetDescriptorsParams().Size();
375  SegmentBoundaries segmentBoundaries(nDescriptors);
376  // segment boundaries for each parameter
377  segmentBoundaries.mArray.SetSize(nDescriptors);
378 
379  for (int z=0;z<nDescriptors;z++)
380  {
381  segmentBoundaries.mArray[z].AddElem(PointTmpl<int,TData>(0,100));//very high value
382  }
383  for (int i=0; i<nFrames-4; i++)
384  {
385  for (int z=0;z<nDescriptors;z++)
386  {
387  const TData & x3 = values.GetAt(z,i+3);
388  const TData & x2 = values.GetAt(z,i+2);
389  const TData & x1 = values.GetAt(z,i+1);
390  const TData & x0 = values.GetAt(z,i);
391  // Avoid div by 0
392  if (x2==0) continue;
393 
394  const TData relevance = fabs((x3-x2)/x2);
395  const TData & ratio = mConfig.GetDescriptorsParams()[z].percentil/100;
396 
397 
398  if ((x3/x2)>(1+ratio) ||
399  (x3/x2)<(1-ratio))
400  {
401  /*
402  if (i>2)
403  {
404  if ((x3/x1)>(1+ratio) || (x3/x1)<(1-ratio))
405  {
406  //if((i-segmentBoundaries.mArray[z][segmentBoundaries.mArray[z].Size()-1])>=mConfig.GetMinSegmentLength())
407  */
408  if (( x3>x2 && x2>x1 && x1>x0 )||
409  ( x3<x2 && x2<x1 && x1<x0 ))
410  {
411  PointTmpl<int,TData> tmpValue(i+3,relevance/ratio);
412  segmentBoundaries.mArray[z].AddElem(tmpValue);
413  }
414  else if((x3/x2)>(1+2*ratio)||
415  (x3/x2)<(1-2*ratio))
416  {
417  PointTmpl<int,TData> tmpValue(i+3,relevance/ratio);
418  segmentBoundaries.mArray[z].AddElem(tmpValue);
419  }
420 
421  }
422  /*
423  }
424  }
425  else if (i>2)
426  {
427  if ((x3/x1)>(1+ratio) || (x3/x1)<(1-ratio))
428  {
429  //if((i-segmentBoundaries.mArray[z][segmentBoundaries.mArray[z].Size()-1])>=mConfig.GetMinSegmentLength())
430  segmentBoundaries.mArray[z].AddElem(i);
431  }
432  }
433  else if (i>3)
434  {
435  if ((x3/x0)>(1+ratio) || (x3/x0)<(1-ratio))
436  {
437  //if((i-segmentBoundaries.mArray[z][segmentBoundaries.mArray[z].Size()-1])>=mConfig.GetMinSegmentLength())
438  segmentBoundaries.mArray[z].AddElem(i);
439  }
440  }
441  */
442  /*
443  if ( x3==0 && x2!=0 )
444  {
445  Point<int,TData> tmpValue(i,100);
446  segmentBoundaries.mArray[z].AddElem(tmpValue);
447  }
448  */
449 
450  }
451  }
452  DataFusion(s,segmentBoundaries);
453 }
454 
455 void Segmentator::DataFusion(Segment& s,const SegmentBoundaries& segmentBoundaries)
456 {
457 
458  // DATA FUSION (of the segmentation parameters), taken from Rossignol's Thesis
459  // DoNothing,1) Generate probability functions for both parameters
460  const int nFrames=s.GetnFrames();
461  const int nDescriptors=mConfig.GetDescriptorsParams().Size();
462  TData duration=s.GetFrame(0).GetDuration();/*BEWARE!Assuming equal lengthed frames*/
463  TData sampleRate=s.GetSamplingRate();
464 
465  /*Initializing Probability Matrix*/
466  Matrix probabilityMatrix(nFrames,nDescriptors);
467  memset(probabilityMatrix.GetBuffer().GetPtr(),0,nFrames*nDescriptors*sizeof(TData));
468 
469  /*Setting probability to one wherever a segment boundary was found*/
470  for (int z=0;z<nDescriptors;z++)
471  {
472  for (int n=0;n<segmentBoundaries.mArray[z].Size();n++)
473  probabilityMatrix.SetAt(segmentBoundaries.mArray[z][n].GetX(),z,segmentBoundaries.mArray[z][n].GetY());
474  }
475 
476  // Adding probability values of different descriptors
477  Array<TData> globalProb;
478  for (int n=0; n<nFrames; n++)
479  {
480  TData tmpProb=0;
481  for(int z=0;z<nDescriptors;z++)
482  {
483  tmpProb+=probabilityMatrix.GetAt(n,z);
484  }
485  globalProb.AddElem(tmpProb);
486  }
487 
488  // MERGE: Two comments, choose one
489  // 3) Fusion of too near marks (separated 1 or 2 frames)
490  // 3) Fusion of too near marks (separated less than the minSegmentLength)
491  // Also compute maximun (to re-use the loop)
492  Array<TData> prob_fusion(globalProb);
493  {
494  int n=0;
495  while(globalProb[n]<=0) // Find first frame with prob>0
496  n++;
497  TData mag=globalProb[n];
498  TData gcenter=n*globalProb[n];
499  prob_fusion[n]=0;
500  for (int m=n+1; m<globalProb.Size(); m++)
501  {
502  if (globalProb[m]<=0) continue;
503  if ((m-n)>mConfig.GetMinSegmentLength())
504  {
505  // Store information and begin another search
506  prob_fusion[(int)(gcenter/mag)]=mag;
507  mag=0;
508  gcenter=0;
509  }
510  mag+=globalProb[m];
511  gcenter+=m*globalProb[m];
512  prob_fusion[m]=0;
513  n=m;
514  }
515  }
516  // 4) DELETE SMALL MARKS (1/7 of the max value, parameter that should be optimized...)
517  TData max=0;
518  for (int n=0; n<prob_fusion.Size(); n++)
519  if (prob_fusion[n]>max)
520  max=prob_fusion[n];
521  for (int n=0; n<prob_fusion.Size(); n++)
522  // MERGE: cuidado max/100 vs. CLAM04 max/7
523  if (prob_fusion[n]<=(max/100))
524  prob_fusion[n]=0;
525 
526  Array<TData> finalSegments; // final segment boundaries in samples
527  for (int n=0; n<prob_fusion.Size(); n++)
528  {
529  if (prob_fusion[n]>0)
530  finalSegments.AddElem(n*duration*sampleRate);
531  }
532 
533  // Store segment boundaries information
534 
535  if (finalSegments.Size()<=0) return;
536 
537  for (int n=0; n<(finalSegments.Size()-1); n++)
538  {
539  Segment tmpSegment;
540  tmpSegment.SetBeginTime(finalSegments[n] /sampleRate);
541  tmpSegment.SetEndTime (finalSegments[n+1]/sampleRate);
542  tmpSegment.SetpParent(&s);
543  tmpSegment.SetHoldsData( false );
544  s.GetChildren().AddElem(tmpSegment);
545  }
546 
547  Segment tmpSegment;
548  tmpSegment.SetBeginTime(finalSegments[finalSegments.Size()-1] /sampleRate);
549  tmpSegment.SetEndTime(s.GetAudio().GetEndTime());
550  tmpSegment.SetpParent(&s);
551  s.GetChildren().AddElem(tmpSegment);
552 
553 }
554