comparison src/Silvet.cpp @ 180:2931089cda46 f0

Have a first go at reporting f0
author Chris Cannam
date Thu, 22 May 2014 16:59:12 +0100
parents 825193ef09d2
children
comparison
equal deleted inserted replaced
179:825193ef09d2 180:2931089cda46
17 #include "EM.h" 17 #include "EM.h"
18 18
19 #include <cq/CQSpectrogram.h> 19 #include <cq/CQSpectrogram.h>
20 20
21 #include "MedianFilter.h" 21 #include "MedianFilter.h"
22 #include "PeakInterpolator.h"
23
22 #include "constant-q-cpp/src/dsp/Resampler.h" 24 #include "constant-q-cpp/src/dsp/Resampler.h"
23 25
24 #include <vector> 26 #include <vector>
25 27
26 #include <cstdio> 28 #include <cstdio>
237 d.isQuantized = false; 239 d.isQuantized = false;
238 d.sampleType = OutputDescriptor::VariableSampleRate; 240 d.sampleType = OutputDescriptor::VariableSampleRate;
239 d.sampleRate = m_inputSampleRate / (m_cq ? m_cq->getColumnHop() : 62); 241 d.sampleRate = m_inputSampleRate / (m_cq ? m_cq->getColumnHop() : 62);
240 d.hasDuration = true; 242 d.hasDuration = true;
241 m_notesOutputNo = list.size(); 243 m_notesOutputNo = list.size();
244 list.push_back(d);
245
246 d.identifier = "f0";
247 d.name = "Predominant fundamental frequency";
248 d.description = "Interpolated frequency of fundamental of most salient pitch at each time frame";
249 d.unit = "Hz";
250 d.hasFixedBinCount = true;
251 d.binCount = 1;
252 d.binNames.push_back("Frequency");
253 d.hasKnownExtents = false;
254 d.isQuantized = false;
255 d.sampleType = OutputDescriptor::FixedSampleRate;
256 d.sampleRate = m_colsPerSec;
257 d.hasDuration = false;
258 m_f0OutputNo = list.size();
242 list.push_back(d); 259 list.push_back(d);
243 260
244 d.identifier = "timefreq"; 261 d.identifier = "timefreq";
245 d.name = "Time-frequency distribution"; 262 d.name = "Time-frequency distribution";
246 d.description = "Filtered constant-Q time-frequency distribution used as input to the expectation-maximisation algorithm"; 263 d.description = "Filtered constant-Q time-frequency distribution used as input to the expectation-maximisation algorithm";
519 } 536 }
520 continue; 537 continue;
521 } 538 }
522 539
523 postProcess(localPitches[i], localBestShifts[i], wantShifts); 540 postProcess(localPitches[i], localBestShifts[i], wantShifts);
541
542 FeatureList f0Features = convertF0Features(filtered[i], shiftCount);
543
544 for (FeatureList::const_iterator fi = f0Features.begin();
545 fi != f0Features.end(); ++fi) {
546 fs[m_f0OutputNo].push_back(*fi);
547 }
524 548
525 FeatureList noteFeatures = noteTrack(shiftCount); 549 FeatureList noteFeatures = noteTrack(shiftCount);
526 550
527 for (FeatureList::const_iterator fi = noteFeatures.begin(); 551 for (FeatureList::const_iterator fi = noteFeatures.begin();
528 fi != noteFeatures.end(); ++fi) { 552 fi != noteFeatures.end(); ++fi) {
652 ValueIndexMap::const_iterator si = strengths.end(); 676 ValueIndexMap::const_iterator si = strengths.end();
653 677
654 map<int, double> active; 678 map<int, double> active;
655 map<int, int> activeShifts; 679 map<int, int> activeShifts;
656 680
681 m_predominantNote = -1;
682 m_predominantShift = -1;
683
657 while (int(active.size()) < polyphony && si != strengths.begin()) { 684 while (int(active.size()) < polyphony && si != strengths.begin()) {
658 685
659 --si; 686 --si;
660 687
661 double strength = si->first; 688 double strength = si->first;
662 int j = si->second; 689 int j = si->second;
663 690
664 active[j] = strength; 691 active[j] = strength;
665 692
693 if (m_predominantNote < 0) {
694 m_predominantNote = j;
695 }
696
666 if (wantShifts) { 697 if (wantShifts) {
698
667 activeShifts[j] = bestShifts[j]; 699 activeShifts[j] = bestShifts[j];
700
701 if (m_predominantShift < 0) {
702 m_predominantShift = bestShifts[j];
703 }
668 } 704 }
669 } 705 }
670 706
671 m_pianoRoll.push_back(active); 707 m_pianoRoll.push_back(active);
672 708
673 if (wantShifts) { 709 if (wantShifts) {
674 m_pianoRollShifts.push_back(activeShifts); 710 m_pianoRollShifts.push_back(activeShifts);
675 } 711 }
712 }
713
714 Vamp::Plugin::FeatureList
715 Silvet::convertF0Features(const vector<double> &column, int shiftCount)
716 {
717 FeatureList fl;
718
719 if (m_predominantNote < 0) {
720 Feature f;
721 f.hasTimestamp = false;
722 f.hasDuration = false;
723 f.values.push_back(0.f);
724 fl.push_back(f);
725 return fl;
726 }
727
728 int f0bin = m_predominantNote * shiftCount;
729
730 if (m_predominantShift >= 0) {
731 f0bin += (shiftCount - m_predominantShift) - int(shiftCount / 2) - 1;
732 }
733
734 PeakInterpolator pi;
735 float interpolated = (float)pi.findPeakLocation
736 (column.data(), column.size(), f0bin);
737
738 float f0 = m_cq->getBinFrequency
739 (m_instruments[0].templateHeight - interpolated - 1.f);
740
741 cerr << "note = " << m_predominantNote << " shift = " << m_predominantShift << " f0bin = " << f0bin << " interpolated = " << interpolated << " f0 = " << f0 << endl;
742
743 Feature f;
744 f.hasTimestamp = false;
745 f.hasDuration = false;
746 f.values.push_back(f0);
747 fl.push_back(f);
748 return fl;
676 } 749 }
677 750
678 Vamp::Plugin::FeatureList 751 Vamp::Plugin::FeatureList
679 Silvet::noteTrack(int shiftCount) 752 Silvet::noteTrack(int shiftCount)
680 { 753 {