comparison src/Silvet.cpp @ 333:19c17cd0c7d8 livemode

Merge
author Chris Cannam
date Thu, 25 Jun 2015 12:21:02 +0100
parents e8e37f471650 4cf4313d7e30
children 806b2ea65416
comparison
equal deleted inserted replaced
332:1272070a1011 333:19c17cd0c7d8
510 CQParameters params(processingSampleRate, 510 CQParameters params(processingSampleRate,
511 minFreq, 511 minFreq,
512 maxFreq, 512 maxFreq,
513 bpo); 513 bpo);
514 514
515 // For params.q, the MIREX code uses 0.8, but it seems that with 515 params.q = 0.8;
516 // atomHopFactor of 0.3, using q == 0.9 or lower drops the FFT 516 params.atomHopFactor = (m_mode == LiveMode ? 1.0 : 0.3);
517 // size to 512 from 1024 and alters some other processing
518 // parameters, making everything much, much slower. Could be a
519 // flaw in the CQ parameter calculations, must check. For
520 // atomHopFactor == 1, q == 0.8 is fine
521 params.q = (m_mode == HighQualityMode ? 0.95 : 0.8);
522 params.atomHopFactor = (m_mode == HighQualityMode ? 0.3 : 1.0);
523 params.threshold = 0.0005; 517 params.threshold = 0.0005;
524 params.decimator = 518 params.decimator =
525 (m_mode == LiveMode ? 519 (m_mode == LiveMode ?
526 CQParameters::FasterDecimator : CQParameters::BetterDecimator); 520 CQParameters::FasterDecimator : CQParameters::BetterDecimator);
527 params.window = CQParameters::Hann; 521 params.window = CQParameters::Hann;
643 637
644 if (filtered.empty()) return; 638 if (filtered.empty()) return;
645 639
646 const InstrumentPack &pack(getPack(m_instrument)); 640 const InstrumentPack &pack(getPack(m_instrument));
647 641
648 for (int i = 0; i < (int)filtered.size(); ++i) { 642 int width = filtered.size();
643
644 double silenceThreshold = 0.01;
645
646 for (int i = 0; i < width; ++i) {
647
648 RealTime timestamp = getColumnTimestamp(m_pianoRoll.size() - 1 + i);
649 float inputGain = getInputGainAt(timestamp);
650
649 Feature f; 651 Feature f;
652 double rms = 0.0;
653
650 for (int j = 0; j < pack.templateHeight; ++j) { 654 for (int j = 0; j < pack.templateHeight; ++j) {
651 f.values.push_back(float(filtered[i][j])); 655 double v = filtered[i][j];
652 } 656 rms += v * v;
657 f.values.push_back(float(v));
658 }
659
660 rms = sqrt(rms / pack.templateHeight);
661 if (rms / inputGain < silenceThreshold) {
662 filtered[i].clear();
663 }
664
653 fs[m_fcqOutputNo].push_back(f); 665 fs[m_fcqOutputNo].push_back(f);
654 } 666 }
655 667
656 int width = filtered.size();
657
658 Grid localPitches(width); 668 Grid localPitches(width);
659 669
660 bool wantShifts = (m_mode == HighQualityMode) && m_fineTuning; 670 bool wantShifts = (m_mode == HighQualityMode) && m_fineTuning;
661 int shiftCount = 1; 671 int shiftCount = 1;
662 if (wantShifts) { 672 if (wantShifts) {
685 vector<EMFuture> results; 695 vector<EMFuture> results;
686 for (int j = 0; j < emThreadCount && i + j < width; ++j) { 696 for (int j = 0; j < emThreadCount && i + j < width; ++j) {
687 results.push_back 697 results.push_back
688 (async(std::launch::async, 698 (async(std::launch::async,
689 [&](int index) { 699 [&](int index) {
690 return applyEM(pack, filtered.at(index), wantShifts); 700 return applyEM
701 (pack, filtered.at(index), wantShifts);
691 }, i + j)); 702 }, i + j));
692 } 703 }
693 for (int j = 0; j < emThreadCount && i + j < width; ++j) { 704 for (int j = 0; j < emThreadCount && i + j < width; ++j) {
694 auto out = results[j].get(); 705 auto out = results[j].get();
695 localPitches[i+j] = out.first; 706 localPitches[i+j] = out.first;
761 bool wantShifts) 772 bool wantShifts)
762 { 773 {
763 double columnThreshold = 1e-5; 774 double columnThreshold = 1e-5;
764 775
765 if (m_mode == LiveMode) { 776 if (m_mode == LiveMode) {
766 columnThreshold /= 20; 777 columnThreshold /= 15;
767 } 778 }
768 779
769 vector<double> pitches(pack.templateNoteCount, 0.0); 780 vector<double> pitches(pack.templateNoteCount, 0.0);
770 vector<int> bestShifts; 781 vector<int> bestShifts;
782
783 if (column.empty()) return { pitches, bestShifts };
771 784
772 double sum = 0.0; 785 double sum = 0.0;
773 for (int j = 0; j < pack.templateHeight; ++j) { 786 for (int j = 0; j < pack.templateHeight; ++j) {
774 sum += column.at(j); 787 sum += column.at(j);
775 } 788 }
921 if (strength < pack.levelThreshold) continue; 934 if (strength < pack.levelThreshold) continue;
922 935
923 // In live mode with only a 12-bpo CQ, we are very likely to 936 // In live mode with only a 12-bpo CQ, we are very likely to
924 // get clusters of two or three high scores at a time for 937 // get clusters of two or three high scores at a time for
925 // neighbouring semitones. Eliminate these by picking only the 938 // neighbouring semitones. Eliminate these by picking only the
926 // peaks. This means we can't recognise actual semitone chords 939 // peaks (except that we never eliminate a note that has
927 // if they ever appear, but it's not as if live mode is good 940 // already been established as currently playing). This means
928 // enough for that to be a big deal anyway. 941 // we can't recognise actual semitone chords if they ever
942 // appear, but it's not as if live mode is good enough for
943 // that to be a big deal anyway.
929 if (m_mode == LiveMode) { 944 if (m_mode == LiveMode) {
930 if (j == 0 || 945 if (m_current.find(j) == m_current.end() &&
931 j + 1 == pack.templateNoteCount || 946 (j == 0 ||
932 pitches[j] < pitches[j-1] || 947 j + 1 == pack.templateNoteCount ||
933 pitches[j] < pitches[j+1]) { 948 pitches[j] < pitches[j-1] ||
949 pitches[j] < pitches[j+1])) {
950 // not a peak or a currently-playing note: skip it
934 continue; 951 continue;
935 } 952 }
936 } 953 }
937 954
938 strengths.insert(ValueIndexMap::value_type(strength, j)); 955 strengths.insert(ValueIndexMap::value_type(strength, j));
1014 if (duration < durationThreshold) { 1031 if (duration < durationThreshold) {
1015 continue; 1032 continue;
1016 } 1033 }
1017 1034
1018 if (duration == durationThreshold) { 1035 if (duration == durationThreshold) {
1036 m_current.insert(note);
1019 emitOnset(start, note, shiftCount, onsetFeatures); 1037 emitOnset(start, note, shiftCount, onsetFeatures);
1020 } 1038 }
1021 1039
1022 if (active.find(note) == active.end()) { 1040 if (active.find(note) == active.end()) {
1023 // the note was playing but just ended 1041 // the note was playing but just ended
1042 m_current.erase(note);
1024 emitNote(start, end, note, shiftCount, noteFeatures); 1043 emitNote(start, end, note, shiftCount, noteFeatures);
1025 } 1044 }
1026 } 1045 }
1027 1046
1028 // cerr << "returning " << noteFeatures.size() << " complete note(s) " << endl; 1047 // cerr << "returning " << noteFeatures.size() << " complete note(s) " << endl;