Mercurial > hg > silvet
comparison src/Silvet.cpp @ 321:213a51e197c8 livemode
Shorten duration threshold for live mode; return non-peak-picked pitch distribution from pitch distribution output
author | Chris Cannam |
---|---|
date | Wed, 29 Apr 2015 10:12:02 +0100 |
parents | 7f9683c8de69 |
children | 6f8fa7fc8fdc |
comparison
equal
deleted
inserted
replaced
320:7f9683c8de69 | 321:213a51e197c8 |
---|---|
708 } | 708 } |
709 } | 709 } |
710 | 710 |
711 for (int i = 0; i < width; ++i) { | 711 for (int i = 0; i < width; ++i) { |
712 | 712 |
713 // This returns a filtered column, and pushes the | 713 vector<double> filtered; |
714 // up-to-max-polyphony activation column to m_pianoRoll | 714 |
715 vector<double> filtered = postProcess | 715 for (int j = 0; j < pack.templateNoteCount; ++j) { |
716 (localPitches[i], localBestShifts[i], wantShifts); | 716 m_postFilter[j]->push(localPitches[i][j]); |
717 filtered.push_back(m_postFilter[j]->get()); | |
718 } | |
717 | 719 |
718 RealTime timestamp = getColumnTimestamp(m_pianoRoll.size() - 1); | 720 RealTime timestamp = getColumnTimestamp(m_pianoRoll.size() - 1); |
719 float inputGain = getInputGainAt(timestamp); | 721 float inputGain = getInputGainAt(timestamp); |
720 | 722 |
721 Feature f; | 723 Feature f; |
730 f.values.resize(12); | 732 f.values.resize(12); |
731 for (int j = 0; j < (int)filtered.size(); ++j) { | 733 for (int j = 0; j < (int)filtered.size(); ++j) { |
732 f.values[j % 12] += filtered[j] / inputGain; | 734 f.values[j % 12] += filtered[j] / inputGain; |
733 } | 735 } |
734 fs[m_chromaOutputNo].push_back(f); | 736 fs[m_chromaOutputNo].push_back(f); |
737 | |
738 // This pushes the up-to-max-polyphony activation column to | |
739 // m_pianoRoll | |
740 postProcess(localPitches[i], localBestShifts[i], wantShifts); | |
735 | 741 |
736 auto events = noteTrack(shiftCount); | 742 auto events = noteTrack(shiftCount); |
737 | 743 |
738 FeatureList noteFeatures = events.first; | 744 FeatureList noteFeatures = events.first; |
739 for (FeatureList::const_iterator fi = noteFeatures.begin(); | 745 for (FeatureList::const_iterator fi = noteFeatures.begin(); |
894 } | 900 } |
895 | 901 |
896 return out; | 902 return out; |
897 } | 903 } |
898 | 904 |
899 vector<double> | 905 void |
900 Silvet::postProcess(const vector<double> &pitches, | 906 Silvet::postProcess(const vector<double> &pitches, |
901 const vector<int> &bestShifts, | 907 const vector<int> &bestShifts, |
902 bool wantShifts) | 908 bool wantShifts) |
903 { | 909 { |
904 const InstrumentPack &pack(getPack(m_instrument)); | 910 const InstrumentPack &pack(getPack(m_instrument)); |
905 | 911 |
906 vector<double> filtered; | 912 // Threshold for level and reduce number of candidate pitches |
913 | |
914 typedef std::multimap<double, int> ValueIndexMap; | |
915 | |
916 ValueIndexMap strengths; | |
907 | 917 |
908 for (int j = 0; j < pack.templateNoteCount; ++j) { | 918 for (int j = 0; j < pack.templateNoteCount; ++j) { |
909 m_postFilter[j]->push(pitches[j]); | 919 |
910 filtered.push_back(m_postFilter[j]->get()); | 920 double strength = pitches[j]; |
911 } | 921 if (strength < pack.levelThreshold) continue; |
912 | 922 |
913 if (m_mode == LiveMode) { | |
914 // In live mode with only a 12-bpo CQ, we are very likely to | 923 // In live mode with only a 12-bpo CQ, we are very likely to |
915 // get clusters of two or three high scores at a time for | 924 // get clusters of two or three high scores at a time for |
916 // neighbouring semitones. Eliminate these by picking only the | 925 // neighbouring semitones. Eliminate these by picking only the |
917 // peaks. This means we can't recognise actual semitone chords | 926 // peaks. This means we can't recognise actual semitone chords |
918 // if they ever appear, but it's not as if live mode is good | 927 // if they ever appear, but it's not as if live mode is good |
919 // enough for that to be a big deal anyway. | 928 // enough for that to be a big deal anyway. |
920 for (int j = 0; j < pack.templateNoteCount; ++j) { | 929 if (m_mode == LiveMode) { |
921 if (j > 0 && j + 1 < pack.templateNoteCount && | 930 if (j == 0 || j + 1 == pack.templateNoteCount || |
922 filtered[j] >= filtered[j-1] && | 931 pitches[j] < pitches[j-1] || |
923 filtered[j] >= filtered[j+1]) { | 932 pitches[j] < pitches[j+1]) { |
924 } else { | 933 continue; |
925 filtered[j] = 0.0; | |
926 } | 934 } |
927 } | 935 } |
928 } | 936 |
929 | |
930 // Threshold for level and reduce number of candidate pitches | |
931 | |
932 typedef std::multimap<double, int> ValueIndexMap; | |
933 | |
934 ValueIndexMap strengths; | |
935 | |
936 for (int j = 0; j < pack.templateNoteCount; ++j) { | |
937 double strength = filtered[j]; | |
938 if (strength < pack.levelThreshold) continue; | |
939 strengths.insert(ValueIndexMap::value_type(strength, j)); | 937 strengths.insert(ValueIndexMap::value_type(strength, j)); |
940 } | 938 } |
941 | 939 |
942 ValueIndexMap::const_iterator si = strengths.end(); | 940 ValueIndexMap::const_iterator si = strengths.end(); |
943 | 941 |
962 | 960 |
963 if (wantShifts) { | 961 if (wantShifts) { |
964 m_pianoRollShifts.push_back(activeShifts); | 962 m_pianoRollShifts.push_back(activeShifts); |
965 } | 963 } |
966 | 964 |
967 return filtered; | 965 return; |
968 } | 966 } |
969 | 967 |
970 pair<Vamp::Plugin::FeatureList, Vamp::Plugin::FeatureList> | 968 pair<Vamp::Plugin::FeatureList, Vamp::Plugin::FeatureList> |
971 Silvet::noteTrack(int shiftCount) | 969 Silvet::noteTrack(int shiftCount) |
972 { | 970 { |
982 const map<int, double> &active = m_pianoRoll[width]; | 980 const map<int, double> &active = m_pianoRoll[width]; |
983 | 981 |
984 double columnDuration = 1.0 / m_colsPerSec; | 982 double columnDuration = 1.0 / m_colsPerSec; |
985 | 983 |
986 // only keep notes >= 100ms or thereabouts | 984 // only keep notes >= 100ms or thereabouts |
987 int durationThreshold = floor(0.1 / columnDuration); // columns | 985 double durationThreshSec = 0.1; |
986 if (m_mode == LiveMode) durationThreshSec = 0.07; | |
987 int durationThreshold = floor(durationThreshSec / columnDuration); // in cols | |
988 if (durationThreshold < 1) durationThreshold = 1; | 988 if (durationThreshold < 1) durationThreshold = 1; |
989 | 989 |
990 FeatureList noteFeatures, onsetFeatures; | 990 FeatureList noteFeatures, onsetFeatures; |
991 | 991 |
992 if (width < durationThreshold + 1) { | 992 if (width < durationThreshold + 1) { |