changeset 35:474f45cfd3fd

Add downsampling outputs -- haven't yet got delay compensation in there though
author Chris Cannam
date Wed, 30 Sep 2015 16:15:36 +0100
parents 156d560d3470
children 13276c5113be
files Makefile.inc src/Chroma.cpp src/Chroma.h src/FeatureDownsample.cpp src/FeatureDownsample.h src/TipicVampPlugin.cpp src/TipicVampPlugin.h
diffstat 7 files changed, 172 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.inc	Wed Sep 30 15:27:04 2015 +0100
+++ b/Makefile.inc	Wed Sep 30 16:15:36 2015 +0100
@@ -24,8 +24,8 @@
 
 PUBLIC_HEADERS	:=
 
-LIB_HEADERS	:= $(SRC_DIR)/delays.h $(SRC_DIR)/filter-a.h $(SRC_DIR)/filter-b.h $(SRC_DIR)/Filter.h $(SRC_DIR)/PitchFilterbank.h $(SRC_DIR)/DCT.h $(SRC_DIR)/Types.h $(SRC_DIR)/CRP.h $(SRC_DIR)/Normalise.h $(SRC_DIR)/LogCompress.h $(SRC_DIR)/OctaveFold.h $(SRC_DIR)/Resize.h $(SRC_DIR)/Chroma.h
-LIB_SOURCES	:= $(SRC_DIR)/Filter.cpp $(SRC_DIR)/PitchFilterbank.cpp $(SRC_DIR)/DCT.cpp $(SRC_DIR)/CRP.cpp $(SRC_DIR)/Normalise.cpp $(SRC_DIR)/Chroma.cpp
+LIB_HEADERS	:= $(SRC_DIR)/delays.h $(SRC_DIR)/filter-a.h $(SRC_DIR)/filter-b.h $(SRC_DIR)/Filter.h $(SRC_DIR)/PitchFilterbank.h $(SRC_DIR)/DCT.h $(SRC_DIR)/Types.h $(SRC_DIR)/CRP.h $(SRC_DIR)/Normalise.h $(SRC_DIR)/LogCompress.h $(SRC_DIR)/OctaveFold.h $(SRC_DIR)/Resize.h $(SRC_DIR)/Chroma.h $(SRC_DIR)/FeatureDownsample.h
+LIB_SOURCES	:= $(SRC_DIR)/Filter.cpp $(SRC_DIR)/PitchFilterbank.cpp $(SRC_DIR)/DCT.cpp $(SRC_DIR)/CRP.cpp $(SRC_DIR)/Normalise.cpp $(SRC_DIR)/Chroma.cpp $(SRC_DIR)/FeatureDownsample.cpp
 LIB_OBJECTS	:= $(LIB_SOURCES:.cpp=.o)
 LIB_OBJECTS	:= $(LIB_OBJECTS:.c=.o)
 
@@ -95,7 +95,6 @@
 
 src/Filter.o: src/Filter.h bqvec/bqvec/Restrict.h bqvec/bqvec/VectorOps.h
 src/Filter.o: bqvec/bqvec/Restrict.h bqvec/bqvec/Allocators.h
-src/Filter.o: bqvec/bqvec/Allocators.h
 src/PitchFilterbank.o: src/PitchFilterbank.h src/Types.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
@@ -103,20 +102,22 @@
 src/CRP.o: src/CRP.h src/Types.h src/DCTReduce.h src/DCT.h src/Normalise.h
 src/CRP.o: src/LogCompress.h src/OctaveFold.h src/Resize.h
 src/Normalise.o: src/Normalise.h
-src/Chroma.o: src/Chroma.h src/Types.h src/Normalise.h src/LogCompress.h
-src/Chroma.o: src/OctaveFold.h src/Resize.h
+src/Chroma.o: src/Chroma.h src/Types.h src/FeatureDownsample.h
+src/Chroma.o: src/Normalise.h src/LogCompress.h src/OctaveFold.h src/Resize.h
+src/FeatureDownsample.o: src/FeatureDownsample.h src/Types.h src/Filter.h
+src/FeatureDownsample.o: bqvec/bqvec/Restrict.h
 src/TipicVampPlugin.o: src/TipicVampPlugin.h src/Types.h
 src/TipicVampPlugin.o: src/PitchFilterbank.h src/CRP.h src/DCTReduce.h
-src/TipicVampPlugin.o: src/DCT.h src/Chroma.h bqvec/bqvec/Range.h
-src/TipicVampPlugin.o: bqvec/bqvec/VectorOps.h bqvec/bqvec/Restrict.h
-src/TipicVampPlugin.o: bqvec/bqvec/Allocators.h
+src/TipicVampPlugin.o: src/DCT.h src/Chroma.h src/FeatureDownsample.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/Types.h
-bqvec/src/Allocators.o: bqvec/bqvec/Allocators.h
 src/test-filter.o: src/Filter.h bqvec/bqvec/Restrict.h
 src/test-dct.o: src/DCT.h
 src/test-normalise.o: src/Normalise.h
 src/Filter.o: bqvec/bqvec/Restrict.h
 src/PitchFilterbank.o: src/Types.h
 src/CRP.o: src/Types.h src/DCTReduce.h src/DCT.h
-src/Chroma.o: src/Types.h
+src/Chroma.o: src/Types.h src/FeatureDownsample.h
+src/FeatureDownsample.o: src/Types.h
 src/TipicVampPlugin.o: src/Types.h
--- a/src/Chroma.cpp	Wed Sep 30 15:27:04 2015 +0100
+++ b/src/Chroma.cpp	Wed Sep 30 16:15:36 2015 +0100
@@ -12,6 +12,11 @@
 
 using namespace std;
 
+Chroma::Chroma(Parameters params) :
+    m_params(params)
+{
+}
+
 Chroma::~Chroma()
 {
 }
--- a/src/Chroma.h	Wed Sep 30 15:27:04 2015 +0100
+++ b/src/Chroma.h	Wed Sep 30 16:15:36 2015 +0100
@@ -5,11 +5,6 @@
 
 #include "Types.h"
 
-//!!! Downsampling/temporal smoothing not yet implemented
-
-//!!! doc: this class has no history, can be used in more than one
-//!!! "channel" at once
-
 class Chroma
 {
 public:
@@ -28,7 +23,7 @@
         { }
     };
 
-    Chroma(Parameters params) : m_params(params) { }
+    Chroma(Parameters params);
     ~Chroma();
 
     RealBlock process(const RealBlock &in);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/FeatureDownsample.cpp	Wed Sep 30 16:15:36 2015 +0100
@@ -0,0 +1,68 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#include "FeatureDownsample.h"
+
+#include "Filter.h"
+#include "Window.h"
+
+#include <stdexcept>
+
+using namespace std;
+
+FeatureDownsample::FeatureDownsample(Parameters params) :
+    m_params(params)
+{
+    if (params.downsampleFactor < 2 || params.windowLength < 2) {
+	throw invalid_argument
+	    ("Expected downsampleFactor and windowLength each to be at least 2");
+    }
+
+    // Our windows are periodic rather than symmetric, but we want a
+    // symmetric window here
+    Window<double> w(HanningWindow, params.windowLength - 1);
+    vector<double> wd(w.getWindowData());
+    wd.push_back(wd[0]);
+
+    // FIR filter
+    for (int i = 0; i < m_params.featureSize; ++i) {
+	m_filters.push_back(new Filter({ {}, wd }));
+    }
+
+    m_toNext = params.downsampleFactor;
+}
+
+FeatureDownsample::~FeatureDownsample()
+{
+    for (auto &f: m_filters) delete f;
+}
+
+void
+FeatureDownsample::reset()
+{
+    for (auto &f: m_filters) f->reset();
+}
+
+RealBlock
+FeatureDownsample::process(const RealBlock &in)
+{
+    //!!! todo: adjust for delay
+    
+    RealBlock out;
+    for (const auto &col: in) {
+	RealColumn outcol;
+	--m_toNext;
+	for (int i = 0; i < m_params.featureSize; ++i) {
+	    double val = 0.0;
+	    m_filters[i]->process(&col[i], &val, 1);
+	    if (m_toNext == 0) {
+		outcol.push_back(val);
+	    }
+	}
+	if (m_toNext == 0) {
+	    out.push_back(outcol);
+	    m_toNext = m_params.downsampleFactor;
+	}
+    }
+    return out;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/FeatureDownsample.h	Wed Sep 30 16:15:36 2015 +0100
@@ -0,0 +1,40 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef FEATURE_DOWNSAMPLE_H
+#define FEATURE_DOWNSAMPLE_H
+
+#include <vector>
+
+#include "Types.h"
+
+//!!! doc: class maintains state
+
+class Filter;
+
+class FeatureDownsample
+{
+public:
+    struct Parameters {
+	int featureSize;
+	int downsampleFactor;
+	int windowLength;
+	Parameters() :
+	    featureSize(1),
+	    downsampleFactor(10),
+	    windowLength(41)
+	{ }
+    };
+
+    FeatureDownsample(Parameters params);
+    ~FeatureDownsample();
+
+    void reset();
+    RealBlock process(const RealBlock &in);
+    
+private:
+    Parameters m_params;
+    std::vector<Filter *> m_filters;
+    int m_toNext;
+};
+
+#endif
--- a/src/TipicVampPlugin.cpp	Wed Sep 30 15:27:04 2015 +0100
+++ b/src/TipicVampPlugin.cpp	Wed Sep 30 16:15:36 2015 +0100
@@ -4,6 +4,7 @@
 #include "PitchFilterbank.h"
 #include "CRP.h"
 #include "Chroma.h"
+#include "FeatureDownsample.h"
 
 #include <bqvec/Range.h>
 #include <bqvec/VectorOps.h>
@@ -39,6 +40,8 @@
     delete m_crp;
     delete m_chroma;
     delete m_logChroma;
+
+    for (auto &d: m_downsamplers) delete d.second;
 }
 
 string
@@ -209,6 +212,11 @@
     m_pitchOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier += "-down";
+    d.name += " (Downsampled)";
+    d.sampleRate /= 10.0;
+    list.push_back(d);
+    
     d.identifier = "cp";
     d.name = "Chroma Pitch Features";
     d.description = "";
@@ -224,18 +232,35 @@
     m_cpOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier += "-down";
+    d.name += " (Downsampled)";
+    d.sampleRate /= 10.0;
+    list.push_back(d);
+
     d.identifier = "clp";
     d.name = "Chroma Log Pitch Features";
     d.description = "";
+    d.sampleRate = PitchFilterbank::getOutputSampleRate();
     m_clpOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier += "-down";
+    d.name += " (Downsampled)";
+    d.sampleRate /= 10.0;
+    list.push_back(d);
+
     d.identifier = "crp";
     d.name = "Chroma DCT-Reduced Log Pitch Features";
     d.description = "";
+    d.sampleRate = PitchFilterbank::getOutputSampleRate();
     m_crpOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier += "-down";
+    d.name += " (Downsampled)";
+    d.sampleRate /= 10.0;
+    list.push_back(d);
+
     return list;
 }
 
@@ -296,6 +321,8 @@
     }
     
     m_filterbank->reset();
+
+    for (auto &d: m_downsamplers) d.second->reset();
 }
 
 Tipic::FeatureSet
@@ -339,6 +366,8 @@
 void
 Tipic::addFeatures(FeatureSet &fs, int outputNo, const RealBlock &block)
 {
+    if (block.empty()) return;
+    
     for (int i = 0; in_range_for(block, i); ++i) {
 	Feature f;
 	int h = block[i].size();
@@ -346,4 +375,20 @@
 	v_convert(f.values.data(), block[i].data(), h);
 	fs[outputNo].push_back(f);
     }
+
+    if (m_downsamplers.find(outputNo) == m_downsamplers.end()) {
+	FeatureDownsample::Parameters params;
+	params.featureSize = block[0].size();
+	m_downsamplers[outputNo] = new FeatureDownsample(params);
+    }
+
+    RealBlock downsampled = m_downsamplers[outputNo]->process(block);
+    
+    for (int i = 0; in_range_for(downsampled, i); ++i) {
+	Feature f;
+	int h = downsampled[i].size();
+	f.values.resize(h);
+	v_convert(f.values.data(), downsampled[i].data(), h);
+	fs[outputNo + 1].push_back(f);
+    }
 }
--- a/src/TipicVampPlugin.h	Wed Sep 30 15:27:04 2015 +0100
+++ b/src/TipicVampPlugin.h	Wed Sep 30 16:15:36 2015 +0100
@@ -8,6 +8,7 @@
 class PitchFilterbank;
 class CRP;
 class Chroma;
+class FeatureDownsample;
 
 using std::string;
 
@@ -60,6 +61,7 @@
     mutable int m_cpOutputNo;
     mutable int m_clpOutputNo;
     mutable int m_crpOutputNo;
+    std::map<int, FeatureDownsample *> m_downsamplers;
 
     void addFeatures(FeatureSet &, int outputNo, const RealBlock &);
 };