Mercurial > hg > tuning-difference
comparison chroma-compare-plugin/TuningDifference.cpp @ 15:994f5294996d
Use Chromagram from libcq, fix incorrect rotation
author | Chris Cannam |
---|---|
date | Thu, 05 Feb 2015 08:38:59 +0000 |
parents | 812e4d021443 |
children | 2c6460fb1fcf |
comparison
equal
deleted
inserted
replaced
14:812e4d021443 | 15:994f5294996d |
---|---|
24 } | 24 } |
25 | 25 |
26 TuningDifference::TuningDifference(float inputSampleRate) : | 26 TuningDifference::TuningDifference(float inputSampleRate) : |
27 Plugin(inputSampleRate), | 27 Plugin(inputSampleRate), |
28 m_bpo(60), | 28 m_bpo(60), |
29 m_refCQ(new CQSpectrogram(paramsForTuningFrequency(440.), | 29 m_refChroma(new Chromagram(paramsForTuningFrequency(440.))) |
30 CQSpectrogram::InterpolateHold)) | |
31 { | 30 { |
32 } | 31 } |
33 | 32 |
34 TuningDifference::~TuningDifference() | 33 TuningDifference::~TuningDifference() |
35 { | 34 { |
239 | 238 |
240 void | 239 void |
241 TuningDifference::reset() | 240 TuningDifference::reset() |
242 { | 241 { |
243 if (m_frameCount > 0) { | 242 if (m_frameCount > 0) { |
244 m_refCQ.reset(new CQSpectrogram(paramsForTuningFrequency(440.), | 243 m_refChroma.reset(new Chromagram(paramsForTuningFrequency(440.))); |
245 CQSpectrogram::InterpolateHold)); | |
246 m_frameCount = 0; | 244 m_frameCount = 0; |
247 } | 245 } |
248 m_refTotals = Chroma(m_refCQ->getTotalBins(), 0.0); | 246 m_refTotals = TFeature(m_bpo, 0.0); |
249 m_other.clear(); | 247 m_other.clear(); |
250 } | 248 } |
251 | 249 |
252 template<typename T> | 250 template<typename T> |
253 void addTo(vector<T> &a, const vector<T> &b) | 251 void addTo(vector<T> &a, const vector<T> &b) |
261 return inner_product(a.begin(), a.end(), b.begin(), T(), | 259 return inner_product(a.begin(), a.end(), b.begin(), T(), |
262 plus<T>(), [](T x, T y) { return fabs(x - y); }); | 260 plus<T>(), [](T x, T y) { return fabs(x - y); }); |
263 } | 261 } |
264 | 262 |
265 TuningDifference::TFeature | 263 TuningDifference::TFeature |
266 TuningDifference::computeFeatureFromTotals(const Chroma &totals) const | 264 TuningDifference::computeFeatureFromTotals(const TFeature &totals) const |
267 { | 265 { |
268 TFeature feature(m_bpo); | 266 TFeature feature(m_bpo); |
269 double sum = 0.0; | 267 double sum = 0.0; |
270 | 268 |
271 for (int i = 0; i < (int)totals.size(); ++i) { | 269 for (int i = 0; i < m_bpo; ++i) { |
272 double value = totals[i] / m_frameCount; | 270 double value = totals[i] / m_frameCount; |
273 feature[i % m_bpo] += value; | 271 feature[i] += value; |
274 sum += value; | 272 sum += value; |
275 } | 273 } |
276 | 274 |
277 for (int i = 0; i < m_bpo; ++i) { | 275 for (int i = 0; i < m_bpo; ++i) { |
278 feature[i] /= sum; | 276 feature[i] /= sum; |
283 cerr << endl; | 281 cerr << endl; |
284 | 282 |
285 return feature; | 283 return feature; |
286 } | 284 } |
287 | 285 |
288 CQParameters | 286 Chromagram::Parameters |
289 TuningDifference::paramsForTuningFrequency(double hz) const | 287 TuningDifference::paramsForTuningFrequency(double hz) const |
290 { | 288 { |
291 return CQParameters(m_inputSampleRate, | 289 Chromagram::Parameters params(m_inputSampleRate); |
292 pitchToFrequency(36, hz), | 290 params.lowestOctave = 0; |
293 pitchToFrequency(96, hz), | 291 params.octaves = 6; |
294 m_bpo); | 292 params.bpo = m_bpo; |
293 params.tuningFrequency = hz; | |
294 return params; | |
295 } | 295 } |
296 | 296 |
297 TuningDifference::TFeature | 297 TuningDifference::TFeature |
298 TuningDifference::computeFeatureFromSignal(const Signal &signal, double hz) const | 298 TuningDifference::computeFeatureFromSignal(const Signal &signal, double hz) const |
299 { | 299 { |
300 CQSpectrogram cq(paramsForTuningFrequency(hz), | 300 Chromagram chromagram(paramsForTuningFrequency(hz)); |
301 CQSpectrogram::InterpolateHold); | 301 |
302 | 302 TFeature totals(m_bpo, 0.0); |
303 Chroma totals(m_refCQ->getTotalBins(), 0.0); | |
304 | 303 |
305 for (int i = 0; i < m_frameCount; ++i) { | 304 for (int i = 0; i < m_frameCount; ++i) { |
306 Signal::const_iterator first = signal.begin() + i * m_blockSize; | 305 Signal::const_iterator first = signal.begin() + i * m_blockSize; |
307 Signal::const_iterator last = first + m_blockSize; | 306 Signal::const_iterator last = first + m_blockSize; |
308 if (last > signal.end()) last = signal.end(); | 307 if (last > signal.end()) last = signal.end(); |
309 CQSpectrogram::RealSequence input(first, last); | 308 CQBase::RealSequence input(first, last); |
310 input.resize(m_blockSize); | 309 input.resize(m_blockSize); |
311 CQSpectrogram::RealBlock block = cq.process(input); | 310 CQBase::RealBlock block = chromagram.process(input); |
312 for (const auto &v: block) addTo(totals, v); | 311 for (const auto &v: block) addTo(totals, v); |
313 } | 312 } |
314 | 313 |
315 return computeFeatureFromTotals(totals); | 314 return computeFeatureFromTotals(totals); |
316 } | 315 } |
317 | 316 |
318 TuningDifference::FeatureSet | 317 TuningDifference::FeatureSet |
319 TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime) | 318 TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime) |
320 { | 319 { |
321 CQSpectrogram::RealBlock block; | 320 CQBase::RealBlock block; |
322 CQSpectrogram::RealSequence input; | 321 CQBase::RealSequence input; |
323 | 322 |
324 input = CQSpectrogram::RealSequence | 323 input = CQBase::RealSequence |
325 (inputBuffers[0], inputBuffers[0] + m_blockSize); | 324 (inputBuffers[0], inputBuffers[0] + m_blockSize); |
326 block = m_refCQ->process(input); | 325 block = m_refChroma->process(input); |
327 for (const auto &v: block) addTo(m_refTotals, v); | 326 for (const auto &v: block) addTo(m_refTotals, v); |
328 | 327 |
329 m_other.insert(m_other.end(), | 328 m_other.insert(m_other.end(), |
330 inputBuffers[1], inputBuffers[1] + m_blockSize); | 329 inputBuffers[1], inputBuffers[1] + m_blockSize); |
331 | 330 |
337 TuningDifference::featureDistance(const TFeature &other, int rotation) const | 336 TuningDifference::featureDistance(const TFeature &other, int rotation) const |
338 { | 337 { |
339 if (rotation == 0) { | 338 if (rotation == 0) { |
340 return distance(m_refFeature, other); | 339 return distance(m_refFeature, other); |
341 } else { | 340 } else { |
341 // A positive rotation pushes the tuning frequency up for this | |
342 // chroma, negative one pulls it down. If a positive rotation | |
343 // makes this chroma match an un-rotated reference, then this | |
344 // chroma must have initially been lower than the reference. | |
342 TFeature r(other); | 345 TFeature r(other); |
343 if (rotation > 0) { | 346 if (rotation < 0) { |
344 rotate(r.begin(), r.begin() + rotation, r.end()); | 347 rotate(r.begin(), r.begin() - rotation, r.end()); |
345 } else { | 348 } else { |
346 rotate(r.begin(), r.end() + rotation, r.end()); | 349 rotate(r.begin(), r.end() - rotation, r.end()); |
347 } | 350 } |
348 return distance(m_refFeature, r); | 351 return distance(m_refFeature, r); |
349 } | 352 } |
350 } | 353 } |
351 | 354 |