changeset 26:3d1c5cabadcc

Add chroma and CLP outputs
author Chris Cannam
date Tue, 29 Sep 2015 17:14:05 +0100
parents 2c913b88b808
children cb86b8b7ed90
files Makefile.inc src/CRP.cpp src/CRP.h src/Chroma.cpp src/Chroma.h src/Normalise.cpp src/Resize.h src/TipicVampPlugin.cpp src/TipicVampPlugin.h
diffstat 9 files changed, 202 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.inc	Tue Sep 29 16:51:49 2015 +0100
+++ b/Makefile.inc	Tue Sep 29 17:14:05 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
-LIB_SOURCES	:= $(SRC_DIR)/Filter.cpp $(SRC_DIR)/PitchFilterbank.cpp $(SRC_DIR)/DCT.cpp $(SRC_DIR)/CRP.cpp $(SRC_DIR)/Normalise.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
+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_OBJECTS	:= $(LIB_SOURCES:.cpp=.o)
 LIB_OBJECTS	:= $(LIB_OBJECTS:.c=.o)
 
@@ -100,17 +100,21 @@
 src/PitchFilterbank.o: bqvec/bqvec/Restrict.h src/delays.h src/filter-a.h
 src/PitchFilterbank.o: src/filter-b.h
 src/DCT.o: src/DCT.h
-src/CRP.o: src/CRP.h src/Types.h src/DCT.h src/Normalise.h src/LogCompress.h
-src/CRP.o: src/OctaveFold.h src/DCTReduce.h
+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/TipicVampPlugin.o: src/TipicVampPlugin.h src/Types.h
-src/TipicVampPlugin.o: src/PitchFilterbank.h src/CRP.h bqvec/bqvec/Range.h
-src/TipicVampPlugin.o: bqvec/bqvec/VectorOps.h bqvec/bqvec/Restrict.h
+src/TipicVampPlugin.o: src/PitchFilterbank.h src/CRP.h src/DCTReduce.h
+src/TipicVampPlugin.o: src/DCT.h bqvec/bqvec/Range.h bqvec/bqvec/VectorOps.h
+src/TipicVampPlugin.o: bqvec/bqvec/Restrict.h
 src/libmain.o: src/TipicVampPlugin.h src/Types.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/CRP.o: src/Types.h src/DCTReduce.h src/DCT.h
+src/Chroma.o: src/Types.h
 src/TipicVampPlugin.o: src/Types.h
--- a/src/CRP.cpp	Tue Sep 29 16:51:49 2015 +0100
+++ b/src/CRP.cpp	Tue Sep 29 17:14:05 2015 +0100
@@ -2,21 +2,23 @@
 
 #include "CRP.h"
 
-#include "DCT.h"
 #include "Normalise.h"
 #include "LogCompress.h"
 #include "OctaveFold.h"
-#include "DCTReduce.h"
+#include "Resize.h"
 
 #include <cmath>
 #include <iostream>
 
 using namespace std;
 
+CRP::CRP(Parameters params) :
+    m_params(params),
+    m_dctReduce(120, params.coefficientsToDrop)
+{}
+
 CRP::~CRP()
-{
-    delete m_dctReduce;
-}
+{}
 
 RealBlock
 CRP::process(const RealBlock &in)
@@ -25,15 +27,6 @@
 	return in;
     }
 
-    // The chroma processing chain requires a 120-bin pitch filterbank
-    // output, even though ours only actually contains 88 bins.
-
-    int size = 120;
-    
-    if (!m_dctReduce) {
-	m_dctReduce = new DCTReduce(size, m_params.coefficientsToDrop);
-    }
-
     RealBlock out;
 
     for (RealColumn col: in) {
@@ -42,13 +35,10 @@
             col = LogCompress::process(col, m_params.logFactor, m_params.logAddTerm);
 	}
 
-        RealColumn resized(20, 0.0);
-        resized.insert(resized.end(), col.begin(), col.end());
-        resized.resize(size);
-        
         out.push_back(Normalise::normalise
                       (OctaveFold::process
-                       (m_dctReduce->process(resized)),
+                       (m_dctReduce.process
+                        (Resize::process(col))),
                        m_params.normP, m_params.normThresh));
     }        
 
--- a/src/CRP.h	Tue Sep 29 16:51:49 2015 +0100
+++ b/src/CRP.h	Tue Sep 29 17:14:05 2015 +0100
@@ -4,11 +4,13 @@
 #define CRP_H
 
 #include "Types.h"
-
-class DCTReduce;
+#include "DCTReduce.h"
 
 //!!! Downsampling/temporal smoothing not yet implemented
 
+//!!! doc: this class has no history, can be used in more than one
+//!!! "channel" at once
+
 class CRP
 {
 public:
@@ -17,7 +19,7 @@
 	bool applyLogCompression;
         double logFactor;
         double logAddTerm;
-        int normP;
+        int normP; // 0 = no normalisation, 1 = L^1, 2 = L^2
         double normThresh;
 	Parameters() :
             coefficientsToDrop(55),
@@ -29,14 +31,14 @@
         { }
     };
 	
-    CRP(Parameters params) : m_params(params), m_dctReduce(0) { }
+    CRP(Parameters params);
     ~CRP();
 
     RealBlock process(const RealBlock &in);
     
 private:
     Parameters m_params;
-    DCTReduce *m_dctReduce;
+    DCTReduce m_dctReduce;
 };
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Chroma.cpp	Tue Sep 29 17:14:05 2015 +0100
@@ -0,0 +1,42 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#include "Chroma.h"
+
+#include "Normalise.h"
+#include "LogCompress.h"
+#include "OctaveFold.h"
+#include "Resize.h"
+
+#include <cmath>
+#include <iostream>
+
+using namespace std;
+
+Chroma::~Chroma()
+{
+}
+
+RealBlock
+Chroma::process(const RealBlock &in)
+{
+    if (in.empty()) {
+	return in;
+    }
+
+    RealBlock out;
+
+    for (RealColumn col: in) {
+
+	if (m_params.applyLogCompression) {
+            col = LogCompress::process(col, m_params.logFactor, m_params.logAddTerm);
+	}
+
+        out.push_back(Normalise::normalise
+                      (OctaveFold::process
+		       (Resize::process(col)),
+		       m_params.normP, m_params.normThresh));
+    }        
+
+    return out;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Chroma.h	Tue Sep 29 17:14:05 2015 +0100
@@ -0,0 +1,41 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef CHROMA_H
+#define CHROMA_H
+
+#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:
+    struct Parameters {
+	bool applyLogCompression;
+	double logFactor;
+	double logAddTerm;
+        int normP; // 0 = no normalisation, 1 = L^1, 2 = L^2
+        double normThresh;
+	Parameters() :
+            applyLogCompression(false),
+            logFactor(100.0),
+            logAddTerm(1.0),
+            normP(2),
+            normThresh(1e-6)
+        { }
+    };
+
+    Chroma(Parameters params) : m_params(params) { }
+    ~Chroma();
+
+    RealBlock process(const RealBlock &in);
+
+private:
+    Parameters m_params;
+};
+
+#endif
+
--- a/src/Normalise.cpp	Tue Sep 29 16:51:49 2015 +0100
+++ b/src/Normalise.cpp	Tue Sep 29 17:14:05 2015 +0100
@@ -17,6 +17,7 @@
 vector<double>
 Normalise::normalise(vector<double> v, int p, double threshold)
 {
+    if (p == 0) return v; // no normalisation
     int n = v.size();
     double nv = norm(v, p);
     if (nv < threshold) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Resize.h	Tue Sep 29 17:14:05 2015 +0100
@@ -0,0 +1,22 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+#ifndef RESIZE_H
+#define RESIZE_H
+
+#include <vector>
+
+class Resize
+{
+public:
+    // The chroma processing chain requires a 120-bin pitch filterbank
+    // output, even though ours only actually contains 88 bins. Zero
+    // pad at both ends here.
+    static std::vector<double> process(std::vector<double> in) {
+	std::vector<double> resized(20, 0.0);
+	resized.insert(resized.end(), in.begin(), in.end());
+	resized.resize(120);
+	return resized;
+    }
+};
+
+#endif
--- a/src/TipicVampPlugin.cpp	Tue Sep 29 16:51:49 2015 +0100
+++ b/src/TipicVampPlugin.cpp	Tue Sep 29 17:14:05 2015 +0100
@@ -3,6 +3,7 @@
 
 #include "PitchFilterbank.h"
 #include "CRP.h"
+#include "Chroma.h"
 
 #include <bqvec/Range.h>
 #include <bqvec/VectorOps.h>
@@ -22,7 +23,11 @@
     m_tuningFrequency(defaultTuningFrequency),
     m_filterbank(0),
     m_crp(0),
+    m_chroma(0),
+    m_logChroma(0),
     m_pitchOutputNo(-1),
+    m_cpOutputNo(-1),
+    m_clpOutputNo(-1),
     m_crpOutputNo(-1)
 {
 }
@@ -30,6 +35,9 @@
 Tipic::~Tipic()
 {
     delete m_filterbank;
+    delete m_crp;
+    delete m_chroma;
+    delete m_logChroma;
 }
 
 string
@@ -182,12 +190,40 @@
     m_pitchOutputNo = list.size();
     list.push_back(d);
 
+    d.identifier = "cp";
+    d.name = "Chroma Pitch Features";
+    d.description = "";
+    d.unit = "";
+    d.hasFixedBinCount = true;
+    d.binCount = 12;
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::FixedSampleRate;
+    d.sampleRate = 22050 / 2205; //!!! get block size & hop from filterbank
+    d.hasDuration = false;
+    m_cpOutputNo = list.size();
+    list.push_back(d);
+
+    d.identifier = "clp";
+    d.name = "Chroma Log Pitch Features";
+    d.description = "";
+    d.unit = "";
+    d.hasFixedBinCount = true;
+    d.binCount = 12;
+    d.hasKnownExtents = false;
+    d.isQuantized = false;
+    d.sampleType = OutputDescriptor::FixedSampleRate;
+    d.sampleRate = 22050 / 2205; //!!! get block size & hop from filterbank
+    d.hasDuration = false;
+    m_clpOutputNo = list.size();
+    list.push_back(d);
+
     d.identifier = "crp";
     d.name = "Chroma DCT-Reduced Log Pitch Features";
     d.description = "";
     d.unit = "";
     d.hasFixedBinCount = true;
-    d.binCount = 12; //!!! make parameter in CRP
+    d.binCount = 12;
     d.hasKnownExtents = false;
     d.isQuantized = false;
     d.sampleType = OutputDescriptor::FixedSampleRate;
@@ -213,7 +249,10 @@
 	// outputNo members
 	(void)getOutputDescriptors();
     }
-    if (m_pitchOutputNo < 0 || m_crpOutputNo < 0) {
+    if (m_pitchOutputNo < 0 ||
+	m_cpOutputNo < 0 ||
+	m_clpOutputNo < 0 ||
+	m_crpOutputNo < 0) {
 	throw std::logic_error("setup went wrong");
     }
     
@@ -240,9 +279,18 @@
 Tipic::reset()
 {
     if (!m_filterbank) {
+
 	m_filterbank = new PitchFilterbank(m_inputSampleRate, m_tuningFrequency);
+
 	m_crp = new CRP({});
+
+	m_chroma = new Chroma({});
+
+	Chroma::Parameters params;
+	params.applyLogCompression = true;
+	m_logChroma = new Chroma(params);
     }
+    
     m_filterbank->reset();
 }
 
@@ -254,11 +302,16 @@
     v_convert(in.data(), inputBuffers[0], m_blockSize);
     
     RealBlock pitchFiltered = m_filterbank->process(in);
-    RealBlock crpReduced = m_crp->process(pitchFiltered);
+
+    RealBlock cp = m_chroma->process(pitchFiltered);
+    RealBlock clp = m_logChroma->process(pitchFiltered);
+    RealBlock crp = m_crp->process(pitchFiltered);
 
     FeatureSet fs;
     addFeatures(fs, m_pitchOutputNo, pitchFiltered);
-    addFeatures(fs, m_crpOutputNo, crpReduced);
+    addFeatures(fs, m_cpOutputNo, cp);
+    addFeatures(fs, m_clpOutputNo, clp);
+    addFeatures(fs, m_crpOutputNo, crp);
     return fs;
 }
 
@@ -266,11 +319,16 @@
 Tipic::getRemainingFeatures()
 {
     RealBlock pitchFiltered = m_filterbank->getRemainingOutput();
-    RealBlock crpReduced = m_crp->process(pitchFiltered);
+
+    RealBlock cp = m_chroma->process(pitchFiltered);
+    RealBlock clp = m_logChroma->process(pitchFiltered);
+    RealBlock crp = m_crp->process(pitchFiltered);
 
     FeatureSet fs;
     addFeatures(fs, m_pitchOutputNo, pitchFiltered);
-    addFeatures(fs, m_crpOutputNo, crpReduced);
+    addFeatures(fs, m_cpOutputNo, cp);
+    addFeatures(fs, m_clpOutputNo, clp);
+    addFeatures(fs, m_crpOutputNo, crp);
     return fs;
 }
 
--- a/src/TipicVampPlugin.h	Tue Sep 29 16:51:49 2015 +0100
+++ b/src/TipicVampPlugin.h	Tue Sep 29 17:14:05 2015 +0100
@@ -7,6 +7,7 @@
 
 class PitchFilterbank;
 class CRP;
+class Chroma;
 
 using std::string;
 
@@ -53,7 +54,11 @@
     float m_tuningFrequency;
     PitchFilterbank *m_filterbank;
     CRP *m_crp;
+    Chroma *m_chroma;
+    Chroma *m_logChroma;
     mutable int m_pitchOutputNo;
+    mutable int m_cpOutputNo;
+    mutable int m_clpOutputNo;
     mutable int m_crpOutputNo;
 
     void addFeatures(FeatureSet &, int outputNo, const RealBlock &);