CLAM-Development  1.4.0
SpectralEnvelopeExtract.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2006 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 "Complex.hxx"
24 #include "Spectrum.hxx"
25 #include "SpecTypeFlags.hxx"
26 #include "SpectralPeakArray.hxx"
27 
28 #define CLASS "SpectralEnvelopeExtract"
29 
30 namespace CLAM {
31 
32  /* The Configuration object has at least to have a name */
33 
35  {
36  AddAll();
37  UpdateData();
38  DefaultValues();
39  }
40 
41 
43  {
44  SetInterpolationType(EInterpolation::eSpline);
45  SetMaxPeaks(200);
46  }
47 
48 
49  /* Processing object Method implementations */
50 
52  {
54  }
55 
57  {
58  Configure(c);
59  }
60 
62  {}
63 
64 
65  /* Configure the Processing Object according to the Config object */
66 
67  bool SpectralEnvelopeExtract::ConcreteConfigure(const ProcessingConfig& c)
68  {
69 
70  CopyAsConcreteConfig(mConfig, c);
71  mMagBPF.SetIntpType(mConfig.GetInterpolationType());
73  return true;
74  }
75 
76  /* Setting Prototypes for faster processing */
77 
79  {
80  return true;
81  }
82 
84  {
85  return true;
86  }
87 
89  {
90  return true;
91  }
92 
93  /* The supervised Do() function */
94 
96  {
97  CLAM_ASSERT(false,CLASS"::Do(): Supervised mode not implemented");
98  return false;
99  }
100 
101  /* The unsupervised Do() function */
102 
104  {
105  output.SetScale(input.GetScale());
106 
107  TSize nPeaks=input.GetnPeaks();
108 
109  if (nPeaks<4) return false; //cannot extract an envelope out of only 3 peaks!
110 
111  CheckOutputType(output);
112 
113  DataArray& magBuffer=input.GetMagBuffer();
114  DataArray& phaseBuffer=input.GetPhaseBuffer();
115  DataArray& freqBuffer=input.GetFreqBuffer();
116 
117  Array<Point>& magPointArray=output.GetMagBPF().GetPointArray();
118  Array<Point>& phasePointArray=output.GetPhaseBPF().GetPointArray();
119 
120  //Max number of points allowed: should be a config param
121  magPointArray.Resize(mConfig.GetMaxPeaks());
122  magPointArray.SetSize(mConfig.GetMaxPeaks());
123  phasePointArray.Resize(mConfig.GetMaxPeaks());
124  phasePointArray.SetSize(mConfig.GetMaxPeaks());
125 
126 
127  for(int i=0;i<nPeaks;i++)
128  {
129  magPointArray[i+1].SetX(freqBuffer[i]);
130  magPointArray[i+1].SetY(magBuffer[i]);
131 
132  phasePointArray[i+1].SetX(freqBuffer[i]);
133  phasePointArray[i+1].SetY(phaseBuffer[i]);
134 
135  }
136 
137  //todo: a lot of duplicated code, should extract in different functions
138  if(input.GetScale()==EScale::eLog)
139  {
140 
141  //we now set first point (maybe we should do the same as with last point?)
142  magPointArray[0].SetX(0);
143  magPointArray[0].SetY(magBuffer[0]-3);
144  phasePointArray[0].SetX(0);
145  phasePointArray[0].SetY(0);
146  nPeaks++;
147 
148  /* we keep adding points to bpf until magnitude is insignificant
149  (note that we add points outside the spectral range) */
150  TData lastFreq=freqBuffer[nPeaks-2];
151  TData freqGap=lastFreq-freqBuffer[nPeaks-3];
152  TData currentFreq=lastFreq+freqGap;
153  TData currentMag=magBuffer[nPeaks-2];
154 
155  while(currentMag>-200)
156  {
157  currentMag-=(currentFreq/lastFreq-1)*12;
158 
159  magPointArray[nPeaks].SetY(currentMag);
160  magPointArray[nPeaks].SetX(currentFreq);
161  phasePointArray[nPeaks].SetY(0);
162  phasePointArray[nPeaks].SetX(currentFreq);
163 
164  currentFreq+=freqGap;
165  nPeaks++;
166  if(nPeaks==mConfig.GetMaxPeaks()) break;
167 
168  }
169  //we resize arrays to final size
170  magPointArray.Resize(nPeaks);
171  magPointArray.SetSize(nPeaks);
172  phasePointArray.Resize(nPeaks);
173  phasePointArray.SetSize(nPeaks);
174 
175 
176  }
177  else
178  {
179  //we now set first point (maybe we should do the same as with last point?)
180  magPointArray[0].SetX(0);
181  magPointArray[0].SetY(magBuffer[0]*0.5);
182  phasePointArray[0].SetX(0);
183  phasePointArray[0].SetY(0);
184  nPeaks++;
185 
186  /* we keep adding points to bpf until magnitude is insignificant
187  (note that we add points outside the spectral range) */
188  TData lastFreq=freqBuffer[nPeaks-2];
189  TData freqGap=lastFreq-freqBuffer[nPeaks-3];
190  TData currentFreq=lastFreq+freqGap;
191  TData currentMag=magBuffer[nPeaks-2];
192 
193 
194  while(currentMag<0.0000000001)
195  {
196  currentMag*=CLAM_pow(0.06,(double)(currentFreq/lastFreq-1.0));
197 
198  magPointArray[nPeaks].SetY(currentMag);
199  magPointArray[nPeaks].SetX(currentFreq);
200  phasePointArray[nPeaks].SetY(0);
201  phasePointArray[nPeaks].SetX(currentFreq);
202 
203  currentFreq+=freqGap;
204  nPeaks++;
205  if(nPeaks==mConfig.GetMaxPeaks()) break;
206  }
207 
208  //we resize arrays to final size
209  magPointArray.Resize(nPeaks);
210  magPointArray.SetSize(nPeaks);
211  phasePointArray.Resize(nPeaks);
212  phasePointArray.SetSize(nPeaks);
213 
214  }
215 
216  output.SetSize(nPeaks);
217  output.GetMagBPF().UpdateSplineTable();
218 
219  return true;
220  }
221 
222  bool SpectralEnvelopeExtract::CheckOutputType(Spectrum& out)
223  {
224  SpecTypeFlags tmpFlags;
225 
226  tmpFlags.bMagPhaseBPF=1;
227  tmpFlags.bMagPhase=0;
228  out.SetType(tmpFlags);
229 
230 
231  out.SetMagBPF(mMagBPF);
232  out.SetPhaseBPF(mPhaseBPF);
233 
234 
235  return true;
236  }
237 };//namespace CLAM
238