Mercurial > hg > silvet
changeset 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 | |
files | .hgsubstate Makefile.inc src/Silvet.cpp src/Silvet.h |
diffstat | 4 files changed, 83 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgsubstate Thu May 22 15:06:37 2014 +0100 +++ b/.hgsubstate Thu May 22 16:59:12 2014 +0100 @@ -1,2 +1,2 @@ a2621605a8c2119bb063c59e83f4fe792a58e4ac bqvec -c7d17fcd215cd2ab66b66c5b89651932cd22d355 constant-q-cpp +c2af8467fce06b2cc259dc8ad279b5019aaf2fbe constant-q-cpp
--- a/Makefile.inc Thu May 22 15:06:37 2014 +0100 +++ b/Makefile.inc Thu May 22 16:59:12 2014 +0100 @@ -19,8 +19,8 @@ PLUGIN := silvet$(PLUGIN_EXT) -PLUGIN_HEADERS := $(SRC_DIR)/Silvet.h $(SRC_DIR)/EM.h $(SRC_DIR)/Instruments.h -PLUGIN_SOURCES := $(SRC_DIR)/Silvet.cpp $(SRC_DIR)/EM.cpp $(SRC_DIR)/Instruments.cpp $(SRC_DIR)/libmain.cpp +PLUGIN_HEADERS := $(SRC_DIR)/Silvet.h $(SRC_DIR)/EM.h $(SRC_DIR)/Instruments.h $(SRC_DIR)/MedianFilter.h $(SRC_DIR)/PeakInterpolator.h +PLUGIN_SOURCES := $(SRC_DIR)/Silvet.cpp $(SRC_DIR)/EM.cpp $(SRC_DIR)/Instruments.cpp $(SRC_DIR)/PeakInterpolator.cpp $(SRC_DIR)/libmain.cpp BQVEC_HEADERS := $(BQVEC_DIR)/Allocators.h $(BQVEC_DIR)/Restrict.h $(BQVEC_DIR)/VectorOps.h BQVEC_SOURCES := $(BQVEC_DIR)/Allocators.cpp @@ -49,7 +49,7 @@ # DO NOT DELETE src/Silvet.o: src/Silvet.h src/MedianFilter.h src/Instruments.h src/EM.h -src/Silvet.o: constant-q-cpp/src/dsp/Resampler.h +src/Silvet.o: src/PeakInterpolator.h constant-q-cpp/src/dsp/Resampler.h src/EM.o: src/EM.h src/Instruments.h src/Instruments.o: src/Instruments.h data/include/templates.h src/Instruments.o: data/include/bassoon.h data/include/cello.h @@ -58,6 +58,7 @@ src/Instruments.o: data/include/oboe.h data/include/tenorsax.h src/Instruments.o: data/include/violin.h data/include/piano1.h src/Instruments.o: data/include/piano2.h data/include/piano3.h +src/PeakInterpolator.o: src/PeakInterpolator.h src/libmain.o: src/Silvet.h src/MedianFilter.h src/Instruments.h bqvec/src/Allocators.o: bqvec/src/Allocators.h bqvec/src/VectorOps.h bqvec/src/Allocators.o: bqvec/src/Restrict.h
--- a/src/Silvet.cpp Thu May 22 15:06:37 2014 +0100 +++ b/src/Silvet.cpp Thu May 22 16:59:12 2014 +0100 @@ -19,6 +19,8 @@ #include <cq/CQSpectrogram.h> #include "MedianFilter.h" +#include "PeakInterpolator.h" + #include "constant-q-cpp/src/dsp/Resampler.h" #include <vector> @@ -241,6 +243,21 @@ m_notesOutputNo = list.size(); list.push_back(d); + d.identifier = "f0"; + d.name = "Predominant fundamental frequency"; + d.description = "Interpolated frequency of fundamental of most salient pitch at each time frame"; + d.unit = "Hz"; + d.hasFixedBinCount = true; + d.binCount = 1; + d.binNames.push_back("Frequency"); + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::FixedSampleRate; + d.sampleRate = m_colsPerSec; + d.hasDuration = false; + m_f0OutputNo = list.size(); + list.push_back(d); + d.identifier = "timefreq"; d.name = "Time-frequency distribution"; d.description = "Filtered constant-Q time-frequency distribution used as input to the expectation-maximisation algorithm"; @@ -521,6 +538,13 @@ } postProcess(localPitches[i], localBestShifts[i], wantShifts); + + FeatureList f0Features = convertF0Features(filtered[i], shiftCount); + + for (FeatureList::const_iterator fi = f0Features.begin(); + fi != f0Features.end(); ++fi) { + fs[m_f0OutputNo].push_back(*fi); + } FeatureList noteFeatures = noteTrack(shiftCount); @@ -654,6 +678,9 @@ map<int, double> active; map<int, int> activeShifts; + m_predominantNote = -1; + m_predominantShift = -1; + while (int(active.size()) < polyphony && si != strengths.begin()) { --si; @@ -663,8 +690,17 @@ active[j] = strength; + if (m_predominantNote < 0) { + m_predominantNote = j; + } + if (wantShifts) { + activeShifts[j] = bestShifts[j]; + + if (m_predominantShift < 0) { + m_predominantShift = bestShifts[j]; + } } } @@ -676,6 +712,43 @@ } Vamp::Plugin::FeatureList +Silvet::convertF0Features(const vector<double> &column, int shiftCount) +{ + FeatureList fl; + + if (m_predominantNote < 0) { + Feature f; + f.hasTimestamp = false; + f.hasDuration = false; + f.values.push_back(0.f); + fl.push_back(f); + return fl; + } + + int f0bin = m_predominantNote * shiftCount; + + if (m_predominantShift >= 0) { + f0bin += (shiftCount - m_predominantShift) - int(shiftCount / 2) - 1; + } + + PeakInterpolator pi; + float interpolated = (float)pi.findPeakLocation + (column.data(), column.size(), f0bin); + + float f0 = m_cq->getBinFrequency + (m_instruments[0].templateHeight - interpolated - 1.f); + + cerr << "note = " << m_predominantNote << " shift = " << m_predominantShift << " f0bin = " << f0bin << " interpolated = " << interpolated << " f0 = " << f0 << endl; + + Feature f; + f.hasTimestamp = false; + f.hasDuration = false; + f.values.push_back(f0); + fl.push_back(f); + return fl; +} + +Vamp::Plugin::FeatureList Silvet::noteTrack(int shiftCount) { // Minimum duration pruning, and conversion to notes. We can only
--- a/src/Silvet.h Thu May 22 15:06:37 2014 +0100 +++ b/src/Silvet.h Thu May 22 16:59:12 2014 +0100 @@ -86,6 +86,8 @@ vector<MedianFilter<double> *> m_postFilter; vector<map<int, double> > m_pianoRoll; vector<map<int, int> > m_pianoRollShifts; + int m_predominantNote; + int m_predominantShift; Grid preProcess(const Grid &); @@ -93,6 +95,8 @@ const vector<int> &bestShifts, bool wantShifts); // -> piano roll column + FeatureList convertF0Features(const vector<double> &cq, int shiftCount); + FeatureList noteTrack(int shiftCount); void emitNote(int start, int end, int note, int shiftCount, @@ -109,6 +113,7 @@ mutable int m_notesOutputNo; mutable int m_fcqOutputNo; + mutable int m_f0OutputNo; }; #endif