Mercurial > hg > tipic
changeset 10:fa87ce20fe8c
Wire up a working plugin. No resampler/filter latency compensation yet, and the code is messy.
author | Chris Cannam |
---|---|
date | Fri, 14 Aug 2015 17:23:56 +0100 |
parents | f440b0e2192b |
children | 7518c113bd03 |
files | Makefile.inc Makefile.linux src/Filter.h src/PitchFilterbank.cpp src/PitchFilterbank.h src/TipicVampPlugin.cpp src/libmain.cpp |
diffstat | 7 files changed, 129 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.inc Fri Aug 14 14:40:48 2015 +0100 +++ b/Makefile.inc Fri Aug 14 17:23:56 2015 +0100 @@ -30,7 +30,7 @@ LIB_OBJECTS := $(LIB_OBJECTS:.c=.o) PLUGIN_HEADERS := $(SRC_DIR)/TipicVampPlugin.h -PLUGIN_SOURCES := $(SRC_DIR)/TipicVampPlugin.cpp +PLUGIN_SOURCES := $(SRC_DIR)/TipicVampPlugin.cpp $(SRC_DIR)/libmain.cpp BQVEC_HEADERS := $(BQVEC_DIR)/Allocators.h $(BQVEC_DIR)/Restrict.h $(BQVEC_DIR)/VectorOps.h BQVEC_SOURCES := $(BQVEC_DIR)/src/Allocators.cpp @@ -74,4 +74,9 @@ src/PitchFilterbank.o: src/PitchFilterbank.h src/Filter.h src/PitchFilterbank.o: bqvec/bqvec/Restrict.h src/delays.h src/filter-a.h src/PitchFilterbank.o: src/filter-b.h +src/TipicVampPlugin.o: src/TipicVampPlugin.h src/PitchFilterbank.h +src/TipicVampPlugin.o: bqvec/bqvec/Range.h bqvec/bqvec/VectorOps.h +src/TipicVampPlugin.o: bqvec/bqvec/Restrict.h +src/libmain.o: src/TipicVampPlugin.h src/PitchFilterbank.h src/Filter.o: bqvec/bqvec/Restrict.h +src/TipicVampPlugin.o: src/PitchFilterbank.h
--- a/Makefile.linux Fri Aug 14 14:40:48 2015 +0100 +++ b/Makefile.linux Fri Aug 14 17:23:56 2015 +0100 @@ -1,7 +1,7 @@ -CFLAGS := -Wall -Werror -O3 -ffast-math -msse -msse2 -mfpmath=sse -ftree-vectorize -fPIC -I../vamp-plugin-sdk/ +#CFLAGS := -Wall -Werror -O3 -ffast-math -msse -msse2 -mfpmath=sse -ftree-vectorize -fPIC -I../vamp-plugin-sdk/ -#CFLAGS := -g -fPIC -I../vamp-plugin-sdk +CFLAGS := -g -fPIC -I../vamp-plugin-sdk CXXFLAGS := $(CFLAGS) -std=c++11
--- a/src/Filter.h Fri Aug 14 14:40:48 2015 +0100 +++ b/src/Filter.h Fri Aug 14 17:23:56 2015 +0100 @@ -19,6 +19,12 @@ ~Filter(); void reset(); + + /** + * Filter the input sequence \arg in of length \arg n samples, and + * write the resulting \arg n samples into \arg out. There must be + * enough room in \arg out for \arg n samples to be written. + */ void process(const double *const BQ_R__ in, double *const BQ_R__ out, const int n); @@ -30,6 +36,9 @@ double *m_b; double *m_inbuf; double *m_outbuf; + + Filter(const Filter &); // not supplied + Filter &operator=(const Filter &); // not supplied }; #endif
--- a/src/PitchFilterbank.cpp Fri Aug 14 14:40:48 2015 +0100 +++ b/src/PitchFilterbank.cpp Fri Aug 14 17:23:56 2015 +0100 @@ -26,16 +26,19 @@ m_to4410(sampleRate, 4410), m_to882(sampleRate, 882) { - for (int i = 0; i < HIGHEST_FILTER_INDEX; ++i) { + for (int i = 0; i <= HIGHEST_FILTER_INDEX; ++i) { int ix = i + 20; int coeffs = sizeof(filter_a[0]) / sizeof(filter_a[0][0]); vector<double> a(filter_a[ix], filter_a[ix] + coeffs); vector<double> b(filter_b[ix], filter_b[ix] + coeffs); - m_filters.push_back(Filter({ a, b })); + m_filters.push_back(new Filter({ a, b })); } } ~D() { + for (int i = 0; i <= HIGHEST_FILTER_INDEX; ++i) { + delete m_filters[i]; + } } int getSampleRate() const { return m_sampleRate; } @@ -49,10 +52,82 @@ /// A matrix of real-valued samples, indexed by time then bin number. typedef vector<RealColumn> RealBlock; - RealBlock process(const RealSequence &); + RealBlock process(const RealSequence &in) { - RealBlock getRemainingOutput(); + m_at22050 = m_to22050.process(in.data(), in.size()); + m_at4410 = m_to4410.process(in.data(), in.size()); + m_at882 = m_to882.process(in.data(), in.size()); + for (int i = 0; i <= HIGHEST_FILTER_INDEX; ++i) { + + if (i <= HIGHEST_FILTER_INDEX_AT_882) { + pushFiltered(i, m_at882); + } else if (i <= HIGHEST_FILTER_INDEX_AT_4410) { + pushFiltered(i, m_at4410); + } else { + pushFiltered(i, m_at22050); + } + } + + //!!! todo make this known through api. these values are at 22050Hz + int windowSize = 4410; + + RealBlock energies(HIGHEST_FILTER_INDEX + 1); + int cols = 0; + + while (m_filtered[HIGHEST_FILTER_INDEX].size() >= unsigned(windowSize)) { + //!!! Quite inefficient -- we're counting everything + //!!! twice. Since there is no actual window shape, isn't + //!!! the overlap just averaging? + for (int i = 0; i <= HIGHEST_FILTER_INDEX; ++i) { + int n = windowSize; + double factor = 1.0; + if (i <= HIGHEST_FILTER_INDEX_AT_882) { + factor = 22050.0 / 882.0; + } else if (i <= HIGHEST_FILTER_INDEX_AT_4410) { + factor = 22050.0 / 4410.0; + } + //!!! Problem -- this is not an integer, for + //!!! fs=882 (it's 176.4) + n = n / factor; + double energy = calculateEnergy(m_filtered[i], n, factor); + energies[i].push_back(energy); + m_filtered[i] = + RealSequence(m_filtered[i].begin() + n/2, m_filtered[i].end()); + } + ++cols; + } + + RealBlock out(cols); + for (int j = 0; j < cols; ++j) { + for (int i = 0; i <= HIGHEST_FILTER_INDEX; ++i) { + out[j].push_back(energies[i][j]); + } + } + + return out; + } + + RealBlock getRemainingOutput() { + //!!! for now! but we do have some buffered + return RealBlock(); + } + + void pushFiltered(int i, const RealSequence &resampled) { + int n = resampled.size(); + RealSequence filtered(n, 0.0); + m_filters[i]->process(resampled.data(), filtered.data(), n); + m_filtered[i].insert(m_filtered[i].end(), filtered.begin(), filtered.end()); + } + + double calculateEnergy(const RealSequence &seq, int n, double factor) { + double energy = 0.0; + for (int i = 0; i < n; ++i) { + energy += seq[i] * seq[i] * factor; + } + return energy; + } + private: int m_sampleRate; @@ -60,6 +135,12 @@ Resampler m_to4410; Resampler m_to882; + RealSequence m_at22050; + RealSequence m_at4410; + RealSequence m_at882; + + RealSequence m_filtered[HIGHEST_FILTER_INDEX + 1]; + Resampler &resamplerFor(int filterIndex) { if (filterIndex < 0) { throw std::logic_error("Filter index is negative"); @@ -79,7 +160,7 @@ // span the MIDI range from pitch 21 to 108. Then m_filters[n] has // coefficients drawn from filter_a[20+n] and filter_b[20+n], and // has effective delay filter_delay[20+n]. - vector<Filter> m_filters; + vector<Filter *> m_filters; int filterIndexForMidiPitch(int pitch) const { return pitch - 21;
--- a/src/PitchFilterbank.h Fri Aug 14 14:40:48 2015 +0100 +++ b/src/PitchFilterbank.h Fri Aug 14 17:23:56 2015 +0100 @@ -29,6 +29,9 @@ private: class D; D *m_d; + + PitchFilterbank(const PitchFilterbank &); // not supplied + PitchFilterbank &operator=(const PitchFilterbank &); // not supplied }; #endif
--- a/src/TipicVampPlugin.cpp Fri Aug 14 14:40:48 2015 +0100 +++ b/src/TipicVampPlugin.cpp Fri Aug 14 17:23:56 2015 +0100 @@ -150,7 +150,8 @@ d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::FixedSampleRate; - d.sampleRate = 4410.0 / m_inputSampleRate; + d.sampleRate = 22050 / 2205; //!!! get block size & hop from filterbank + cerr << "output sampleRate = " << d.sampleRate << endl; d.hasDuration = false; m_pitchOutputNo = list.size(); list.push_back(d);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmain.cpp Fri Aug 14 17:23:56 2015 +0100 @@ -0,0 +1,21 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include <vamp/vamp.h> +#include <vamp-sdk/PluginAdapter.h> + +#include "TipicVampPlugin.h" + +static Vamp::PluginAdapter<Tipic> tipicAdapter; + +const VampPluginDescriptor * +vampGetPluginDescriptor(unsigned int version, unsigned int index) +{ + if (version < 1) return 0; + + switch (index) { + case 0: return tipicAdapter.getDescriptor(); + default: return 0; + } +} + +