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