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