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