Mercurial > hg > chp
comparison ConstrainedHarmonicPeak.cpp @ 1:ab0b04e1c56b
Implement the plugin!
author | Chris Cannam |
---|---|
date | Fri, 07 Mar 2014 15:51:20 +0000 |
parents | f559ab000b67 |
children | 3bf29717cc01 |
comparison
equal
deleted
inserted
replaced
0:f559ab000b67 | 1:ab0b04e1c56b |
---|---|
10 | 10 |
11 ConstrainedHarmonicPeak::ConstrainedHarmonicPeak(float inputSampleRate) : | 11 ConstrainedHarmonicPeak::ConstrainedHarmonicPeak(float inputSampleRate) : |
12 Plugin(inputSampleRate), | 12 Plugin(inputSampleRate), |
13 m_blockSize(0), | 13 m_blockSize(0), |
14 m_minFreq(0), | 14 m_minFreq(0), |
15 m_maxFreq(inputSampleRate/2) | 15 m_maxFreq(inputSampleRate/2), |
16 m_harmonics(5) | |
16 { | 17 { |
17 } | 18 } |
18 | 19 |
19 ConstrainedHarmonicPeak::~ConstrainedHarmonicPeak() | 20 ConstrainedHarmonicPeak::~ConstrainedHarmonicPeak() |
20 { | 21 { |
111 d.maxValue = m_inputSampleRate/2; | 112 d.maxValue = m_inputSampleRate/2; |
112 d.defaultValue = 0; | 113 d.defaultValue = 0; |
113 d.isQuantized = false; | 114 d.isQuantized = false; |
114 list.push_back(d); | 115 list.push_back(d); |
115 | 116 |
117 d.identifier = "harmonics"; | |
118 d.name = "Harmonics"; | |
119 d.description = "Maximum number of harmonics to consider"; | |
120 d.unit = ""; | |
121 d.minValue = 1; | |
122 d.maxValue = 20; | |
123 d.defaultValue = 5; | |
124 d.isQuantized = true; | |
125 d.quantizeStep = 1; | |
126 list.push_back(d); | |
127 | |
116 return list; | 128 return list; |
117 } | 129 } |
118 | 130 |
119 float | 131 float |
120 ConstrainedHarmonicPeak::getParameter(string identifier) const | 132 ConstrainedHarmonicPeak::getParameter(string identifier) const |
121 { | 133 { |
122 if (identifier == "minfreq") { | 134 if (identifier == "minfreq") { |
123 return m_minFreq; | 135 return m_minFreq; |
124 } else if (identifier == "maxfreq") { | 136 } else if (identifier == "maxfreq") { |
125 return m_maxFreq; | 137 return m_maxFreq; |
138 } else if (identifier == "harmonics") { | |
139 return m_harmonics; | |
126 } | 140 } |
127 return 0; | 141 return 0; |
128 } | 142 } |
129 | 143 |
130 void | 144 void |
132 { | 146 { |
133 if (identifier == "minfreq") { | 147 if (identifier == "minfreq") { |
134 m_minFreq = value; | 148 m_minFreq = value; |
135 } else if (identifier == "maxfreq") { | 149 } else if (identifier == "maxfreq") { |
136 m_maxFreq = value; | 150 m_maxFreq = value; |
151 } else if (identifier == "harmonics") { | |
152 m_harmonics = int(round(value)); | |
137 } | 153 } |
138 } | 154 } |
139 | 155 |
140 ConstrainedHarmonicPeak::ProgramList | 156 ConstrainedHarmonicPeak::ProgramList |
141 ConstrainedHarmonicPeak::getPrograms() const | 157 ConstrainedHarmonicPeak::getPrograms() const |
191 void | 207 void |
192 ConstrainedHarmonicPeak::reset() | 208 ConstrainedHarmonicPeak::reset() |
193 { | 209 { |
194 } | 210 } |
195 | 211 |
212 double | |
213 ConstrainedHarmonicPeak::findInterpolatedPeak(const double *in, | |
214 int peakbin, | |
215 int bins) | |
216 { | |
217 // duplicate with SimpleCepstrum plugin | |
218 // after jos, | |
219 // https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html | |
220 | |
221 if (peakbin < 1 || peakbin > bins - 2) { | |
222 return peakbin; | |
223 } | |
224 | |
225 double alpha = in[peakbin-1]; | |
226 double beta = in[peakbin]; | |
227 double gamma = in[peakbin+1]; | |
228 | |
229 double denom = (alpha - 2*beta + gamma); | |
230 | |
231 if (denom == 0) { | |
232 // flat | |
233 return peakbin; | |
234 } | |
235 | |
236 double p = ((alpha - gamma) / denom) / 2.0; | |
237 | |
238 return double(peakbin) + p; | |
239 } | |
240 | |
196 ConstrainedHarmonicPeak::FeatureSet | 241 ConstrainedHarmonicPeak::FeatureSet |
197 ConstrainedHarmonicPeak::process(const float *const *inputBuffers, Vamp::RealTime timestamp) | 242 ConstrainedHarmonicPeak::process(const float *const *inputBuffers, Vamp::RealTime timestamp) |
198 { | 243 { |
199 FeatureSet fs; | 244 FeatureSet fs; |
200 | 245 |
246 int hs = m_blockSize/2; | |
247 | |
248 double *mags = new double[hs+1]; | |
249 for (int i = 0; i <= hs; ++i) { | |
250 mags[i] = sqrtf(inputBuffers[0][i*2] * inputBuffers[0][i*2] + | |
251 inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); | |
252 } | |
253 | |
254 // bin freq is bin * samplerate / fftsize | |
255 | |
256 int minbin = int(floor((m_minFreq * m_blockSize) / m_inputSampleRate)); | |
257 int maxbin = int(ceil((m_maxFreq * m_blockSize) / m_inputSampleRate)); | |
258 if (minbin > hs) minbin = hs; | |
259 if (maxbin > hs) maxbin = hs; | |
260 if (maxbin <= minbin) return fs; | |
261 | |
262 double *hps = new double[maxbin - minbin + 1]; | |
263 | |
264 // HPS in dB after MzHarmonicSpectrum | |
265 | |
266 for (int bin = minbin; bin <= maxbin; ++bin) { | |
267 | |
268 int i = bin - minbin; | |
269 hps[i] = 1.0; | |
270 | |
271 int contributing = 0; | |
272 | |
273 for (int j = 1; j <= m_harmonics; ++j) { | |
274 if (j * bin > hs) break; | |
275 hps[i] *= mags[j * bin]; | |
276 ++contributing; | |
277 } | |
278 | |
279 if (hps[i] <= 0.0) { | |
280 hps[i] = -120.0; | |
281 } else { | |
282 hps[i] = 20.0 / contributing * log10(hps[i]); | |
283 } | |
284 } | |
285 | |
286 double maxdb = -120.0; | |
287 int maxidx = 0; | |
288 for (int i = 0; i <= maxbin - minbin; ++i) { | |
289 if (hps[i] > maxdb) { | |
290 maxdb = hps[i]; | |
291 maxidx = i; | |
292 } | |
293 } | |
294 | |
295 double interpolated = findInterpolatedPeak(hps, maxidx, maxbin - minbin + 1); | |
296 interpolated = interpolated + minbin; | |
297 | |
298 double freq = interpolated * m_inputSampleRate / m_blockSize; | |
299 | |
300 Feature f; | |
301 f.values.push_back(freq); | |
302 fs[0].push_back(f); | |
303 | |
201 return fs; | 304 return fs; |
202 } | 305 } |
203 | 306 |
204 ConstrainedHarmonicPeak::FeatureSet | 307 ConstrainedHarmonicPeak::FeatureSet |
205 ConstrainedHarmonicPeak::getRemainingFeatures() | 308 ConstrainedHarmonicPeak::getRemainingFeatures() |
206 { | 309 { |
207 FeatureSet fs; | 310 FeatureSet fs; |
208 | |
209 return fs; | 311 return fs; |
210 } | 312 } |
211 | 313 |