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;
+    }
+}
+
+