Mercurial > hg > silvet
comparison src/Silvet.cpp @ 170:2114b2545c27 finetune
Refactor to avoid allocating 300 EM objects at a time!
author | Chris Cannam |
---|---|
date | Wed, 21 May 2014 11:53:31 +0100 |
parents | 192c4ba3de45 |
children | 06d19c847a41 |
comparison
equal
deleted
inserted
replaced
169:192c4ba3de45 | 170:2114b2545c27 |
---|---|
31 using std::endl; | 31 using std::endl; |
32 using Vamp::RealTime; | 32 using Vamp::RealTime; |
33 | 33 |
34 static int processingSampleRate = 44100; | 34 static int processingSampleRate = 44100; |
35 static int processingBPO = 60; | 35 static int processingBPO = 60; |
36 | |
37 //!!! todo: replace these two with values from instrument pack | |
36 static int processingHeight = 545; | 38 static int processingHeight = 545; |
37 static int processingNotes = 88; | 39 static int processingNotes = 88; |
38 | 40 |
39 Silvet::Silvet(float inputSampleRate) : | 41 Silvet::Silvet(float inputSampleRate) : |
40 Plugin(inputSampleRate), | 42 Plugin(inputSampleRate), |
380 Grid filtered = preProcess(cqout); | 382 Grid filtered = preProcess(cqout); |
381 | 383 |
382 FeatureSet fs; | 384 FeatureSet fs; |
383 | 385 |
384 if (filtered.empty()) return fs; | 386 if (filtered.empty()) return fs; |
387 | |
388 const InstrumentPack &pack = m_instruments[m_instrument]; | |
385 | 389 |
386 int width = filtered.size(); | 390 int width = filtered.size(); |
387 | 391 |
388 int iterations = m_hqMode ? 20 : 10; | 392 int iterations = m_hqMode ? 20 : 10; |
389 | 393 |
390 vector<EM *> em(width, (EM *)0); | 394 //!!! pitches or notes? [terminology] |
391 vector<double> sums(width, 0.0); | 395 Grid localPitches(width, vector<double>(processingNotes, 0.0)); |
396 | |
397 bool wantShifts = m_hqMode && m_fineTuning; | |
398 int shiftCount = 1; | |
399 if (wantShifts) { | |
400 shiftCount = pack.templateMaxShift * 2 + 1; | |
401 } | |
402 | |
403 vector<vector<int> > localBestShifts; | |
404 if (wantShifts) { | |
405 localBestShifts = | |
406 vector<vector<int> >(width, vector<int>(processingNotes, 0)); | |
407 } | |
408 | |
409 vector<bool> present(width, false); | |
392 | 410 |
393 #pragma omp parallel for | 411 #pragma omp parallel for |
394 for (int i = 0; i < width; ++i) { | 412 for (int i = 0; i < width; ++i) { |
395 | 413 |
414 double sum = 0.0; | |
396 for (int j = 0; j < processingHeight; ++j) { | 415 for (int j = 0; j < processingHeight; ++j) { |
397 sums[i] += filtered.at(i).at(j); | 416 sum += filtered.at(i).at(j); |
398 } | 417 } |
399 | 418 if (sum < 1e-5) continue; |
400 if (sums[i] < 1e-5) continue; | 419 |
401 | 420 present[i] = true; |
402 em[i] = new EM(&m_instruments[m_instrument], m_hqMode); | 421 |
422 EM em(&pack, m_hqMode); | |
403 | 423 |
404 for (int j = 0; j < iterations; ++j) { | 424 for (int j = 0; j < iterations; ++j) { |
405 em[i]->iterate(filtered.at(i).data()); | 425 em.iterate(filtered.at(i).data()); |
406 } | 426 } |
407 } | 427 |
408 | 428 const float *pitchDist = em.getPitchDistribution(); |
409 int shiftCount = 1; | 429 const float *const *shiftDist = em.getShifts(); |
410 | 430 |
411 if (m_hqMode && m_fineTuning) { | 431 for (int j = 0; j < processingNotes; ++j) { |
412 shiftCount = m_instruments[m_instrument].templateMaxShift * 2 + 1; | 432 |
433 localPitches[i][j] = pitchDist[j] * sum; | |
434 | |
435 int bestShift = 0; | |
436 int bestShiftValue = 0.0; | |
437 if (wantShifts) { | |
438 for (int k = 0; k < shiftCount; ++k) { | |
439 if (k == 0 || shiftDist[k][j] > bestShiftValue) { | |
440 bestShiftValue = shiftDist[k][j]; | |
441 bestShift = k; | |
442 } | |
443 } | |
444 localBestShifts[i][j] = bestShift; | |
445 } | |
446 } | |
413 } | 447 } |
414 | 448 |
415 for (int i = 0; i < width; ++i) { | 449 for (int i = 0; i < width; ++i) { |
416 | 450 |
417 if (!em[i]) { | 451 if (!present[i]) { |
452 // silent column | |
453 for (int j = 0; j < processingNotes; ++j) { | |
454 m_postFilter[j]->push(0.0); | |
455 } | |
418 m_pianoRoll.push_back(map<int, double>()); | 456 m_pianoRoll.push_back(map<int, double>()); |
419 if (shiftCount > 1) { | 457 if (wantShifts) { |
420 m_pianoRollShifts.push_back(map<int, int>()); | 458 m_pianoRollShifts.push_back(map<int, int>()); |
421 } | 459 } |
422 continue; | 460 continue; |
423 } | 461 } |
424 | 462 |
425 postProcess(em[i]->getPitchDistribution(), | 463 postProcess(localPitches[i], localBestShifts[i], wantShifts); |
426 em[i]->getShifts(), | |
427 shiftCount, | |
428 sums[i]); | |
429 | |
430 delete em[i]; | |
431 | 464 |
432 FeatureList noteFeatures = noteTrack(shiftCount); | 465 FeatureList noteFeatures = noteTrack(shiftCount); |
433 | 466 |
434 for (FeatureList::const_iterator fi = noteFeatures.begin(); | 467 for (FeatureList::const_iterator fi = noteFeatures.begin(); |
435 fi != noteFeatures.end(); ++fi) { | 468 fi != noteFeatures.end(); ++fi) { |
506 | 539 |
507 return out; | 540 return out; |
508 } | 541 } |
509 | 542 |
510 void | 543 void |
511 Silvet::postProcess(const float *pitches, | 544 Silvet::postProcess(const vector<double> &pitches, |
512 const float *const *shifts, | 545 const vector<int> &bestShifts, |
513 int shiftCount, | 546 bool wantShifts) |
514 double gain) | |
515 { | 547 { |
516 vector<double> filtered; | 548 vector<double> filtered; |
517 | 549 |
518 for (int j = 0; j < processingNotes; ++j) { | 550 for (int j = 0; j < processingNotes; ++j) { |
519 m_postFilter[j]->push(pitches[j] * gain); | 551 m_postFilter[j]->push(pitches[j]); |
520 filtered.push_back(m_postFilter[j]->get()); | 552 filtered.push_back(m_postFilter[j]->get()); |
521 } | 553 } |
522 | 554 |
523 // Threshold for level and reduce number of candidate pitches | 555 // Threshold for level and reduce number of candidate pitches |
524 | 556 |
531 typedef std::multimap<double, int> ValueIndexMap; | 563 typedef std::multimap<double, int> ValueIndexMap; |
532 | 564 |
533 ValueIndexMap strengths; | 565 ValueIndexMap strengths; |
534 | 566 |
535 for (int j = 0; j < processingNotes; ++j) { | 567 for (int j = 0; j < processingNotes; ++j) { |
536 | |
537 double strength = filtered[j]; | 568 double strength = filtered[j]; |
538 if (strength < threshold) continue; | 569 if (strength < threshold) continue; |
539 | |
540 strengths.insert(ValueIndexMap::value_type(strength, j)); | 570 strengths.insert(ValueIndexMap::value_type(strength, j)); |
541 } | 571 } |
542 | 572 |
543 ValueIndexMap::const_iterator si = strengths.end(); | 573 ValueIndexMap::const_iterator si = strengths.end(); |
544 | 574 |
552 double strength = si->first; | 582 double strength = si->first; |
553 int j = si->second; | 583 int j = si->second; |
554 | 584 |
555 active[j] = strength; | 585 active[j] = strength; |
556 | 586 |
557 if (shiftCount > 1) { | 587 if (wantShifts) { |
558 | 588 activeShifts[j] = bestShifts[j]; |
559 // find preferred shift f for note j | |
560 int bestShift = 0; | |
561 float bestShiftValue = 0.f; | |
562 for (int f = 0; f < shiftCount; ++f) { | |
563 if (f == 0 || shifts[f][j] > bestShiftValue) { | |
564 bestShiftValue = shifts[f][j]; | |
565 bestShift = f; | |
566 } | |
567 } | |
568 | |
569 activeShifts[j] = bestShift; | |
570 } | 589 } |
571 } | 590 } |
572 | 591 |
573 m_pianoRoll.push_back(active); | 592 m_pianoRoll.push_back(active); |
574 if (shiftCount > 1) { | 593 |
594 if (wantShifts) { | |
575 m_pianoRollShifts.push_back(activeShifts); | 595 m_pianoRollShifts.push_back(activeShifts); |
576 } | 596 } |
577 } | 597 } |
578 | 598 |
579 Vamp::Plugin::FeatureList | 599 Vamp::Plugin::FeatureList |