changeset 172:76b70af3a563

Merge from branch chroma-in-library
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 05 Feb 2015 09:53:06 +0000
parents 8a1d240ac542 (current diff) a12642e36167 (diff)
children 223f2a8c4f65
files vamp/Pitch.cpp vamp/Pitch.h
diffstat 9 files changed, 404 insertions(+), 197 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.inc	Wed Jan 14 18:00:34 2015 +0000
+++ b/Makefile.inc	Thu Feb 05 09:53:06 2015 +0000
@@ -36,6 +36,8 @@
 	$(INC_DIR)/ConstantQ.h \
 	$(INC_DIR)/CQSpectrogram.h \
 	$(INC_DIR)/CQInverse.h \
+	$(INC_DIR)/Chromagram.h \
+	$(LIB_DIR)/Pitch.h \
 	$(LIB_DIR)/dsp/FFT.h \
 	$(LIB_DIR)/dsp/KaiserWindow.h \
 	$(LIB_DIR)/dsp/MathUtilities.h \
@@ -51,6 +53,8 @@
 	$(LIB_DIR)/ConstantQ.cpp \
 	$(LIB_DIR)/CQSpectrogram.cpp \
 	$(LIB_DIR)/CQInverse.cpp \
+	$(LIB_DIR)/Chromagram.cpp \
+	$(LIB_DIR)/Pitch.cpp \
 	$(LIB_DIR)/dsp/FFT.cpp \
 	$(LIB_DIR)/dsp/KaiserWindow.cpp \
 	$(LIB_DIR)/dsp/MathUtilities.cpp \
@@ -61,15 +65,13 @@
 
 VAMP_HEADERS	:= \
 	$(VAMP_DIR)/CQVamp.h \
-	$(VAMP_DIR)/CQChromaVamp.h \
-	$(VAMP_DIR)/Pitch.h
+	$(VAMP_DIR)/CQChromaVamp.h
 
 VAMP_SOURCES	:= \
 	$(VAMP_DIR)/CQVamp.cpp \
 	$(VAMP_DIR)/CQChromaVamp.cpp \
-	$(VAMP_DIR)/libmain.cpp \
-	$(VAMP_DIR)/Pitch.cpp
-
+	$(VAMP_DIR)/libmain.cpp
+	
 TEST_SOURCES	:= \
 	$(TEST_DIR)/TestFFT.cpp \
 	$(TEST_DIR)/TestMathUtilities.cpp \
@@ -136,6 +138,8 @@
 src/ConstantQ.o: src/dsp/nan-inf.h src/dsp/FFT.h
 src/CQInverse.o: src/dsp/Resampler.h src/dsp/MathUtilities.h
 src/CQInverse.o: src/dsp/nan-inf.h src/dsp/FFT.h
+src/Chromagram.o: src/Pitch.h
+src/Pitch.o: src/Pitch.h
 src/dsp/FFT.o: src/dsp/FFT.h src/dsp/MathUtilities.h src/dsp/nan-inf.h
 src/dsp/KaiserWindow.o: src/dsp/KaiserWindow.h src/dsp/MathUtilities.h
 src/dsp/KaiserWindow.o: src/dsp/nan-inf.h
@@ -150,12 +154,11 @@
 src/ext/kissfft/tools/kiss_fftr.o: src/ext/kissfft/kiss_fft.h
 src/ext/kissfft/tools/kiss_fftr.o: src/ext/kissfft/_kiss_fft_guts.h
 vamp/CQVamp.o: vamp/CQVamp.h cq/CQSpectrogram.h cq/ConstantQ.h cq/CQBase.h
-vamp/CQVamp.o: cq/CQParameters.h cq/CQKernel.h vamp/Pitch.h
+vamp/CQVamp.o: cq/CQParameters.h cq/CQKernel.h src/Pitch.h
 vamp/CQChromaVamp.o: vamp/CQChromaVamp.h cq/CQSpectrogram.h cq/ConstantQ.h
-vamp/CQChromaVamp.o: cq/CQBase.h cq/CQParameters.h cq/CQKernel.h vamp/Pitch.h
+vamp/CQChromaVamp.o: cq/CQBase.h cq/CQParameters.h cq/CQKernel.h
 vamp/libmain.o: vamp/CQVamp.h cq/CQSpectrogram.h cq/ConstantQ.h cq/CQBase.h
 vamp/libmain.o: cq/CQParameters.h cq/CQKernel.h vamp/CQChromaVamp.h
-vamp/Pitch.o: vamp/Pitch.h
 test/TestFFT.o: src/dsp/FFT.h
 test/TestMathUtilities.o: src/dsp/MathUtilities.h src/dsp/nan-inf.h
 test/TestResampler.o: src/dsp/Resampler.h src/dsp/Window.h src/dsp/FFT.h
@@ -172,6 +175,7 @@
 cq/CQSpectrogram.o: cq/ConstantQ.h cq/CQBase.h cq/CQParameters.h
 cq/CQSpectrogram.o: cq/CQKernel.h
 cq/CQInverse.o: cq/CQBase.h cq/CQKernel.h cq/CQParameters.h
+cq/Chromagram.o: cq/CQBase.h
 src/dsp/MathUtilities.o: src/dsp/nan-inf.h
 src/ext/kissfft/tools/kiss_fftr.o: src/ext/kissfft/kiss_fft.h
 vamp/CQVamp.o: cq/CQSpectrogram.h cq/ConstantQ.h cq/CQBase.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cq/Chromagram.h	Thu Feb 05 09:53:06 2015 +0000
@@ -0,0 +1,94 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    Constant-Q library
+    Copyright (c) 2013-2015 Queen Mary, University of London
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef CQCHROMAGRAM_H
+#define CQCHROMAGRAM_H
+
+#include "CQBase.h"
+#include "CQParameters.h"
+
+class CQSpectrogram;
+
+class Chromagram
+{
+public:
+    struct Parameters {
+	Parameters(double sr) :
+	    sampleRate(sr),
+	    lowestOctave(0),
+	    octaveCount(7),
+	    binsPerOctave(36),
+	    tuningFrequency(440.),
+            q(1.0),                    // Q scaling factor
+            atomHopFactor(0.25),       // hop size of shortest temporal atom
+            threshold(0.0005),         // sparsity threshold for resulting kernel
+            window(CQParameters::SqrtBlackmanHarris) // window shape
+        { }
+        
+	double sampleRate;
+	int lowestOctave;
+	int octaveCount;
+	int binsPerOctave;
+
+	double tuningFrequency;
+        double q;
+        double atomHopFactor;
+        double threshold;
+        CQParameters::WindowType window;
+    };
+
+    Chromagram(Parameters params);
+    virtual ~Chromagram();
+
+    CQBase::RealBlock process(const CQBase::RealSequence &);
+    CQBase::RealBlock getRemainingOutput();
+
+    double getMinFrequency() const { return m_minFrequency; }
+    double getMaxFrequency() const { return m_maxFrequency; }
+
+    std::string getBinName(int bin) const;
+    
+    bool isValid() const;
+    int getColumnHop() const;
+    int getLatency() const;
+    
+private:
+    Parameters m_params;
+    CQSpectrogram *m_cq;
+    double m_minFrequency;
+    double m_maxFrequency;
+    CQBase::RealBlock convert(const CQBase::RealBlock &);
+};
+
+#endif
+
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Chromagram.cpp	Thu Feb 05 09:53:06 2015 +0000
@@ -0,0 +1,154 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    Constant-Q library
+    Copyright (c) 2013-2015 Queen Mary, University of London
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "Chromagram.h"
+#include "CQSpectrogram.h"
+#include "Pitch.h"
+
+#include <cstdio>
+
+using namespace std;
+
+Chromagram::Chromagram(Parameters params) :
+    m_params(params),
+    m_cq(0)
+{
+    int highestOctave = m_params.lowestOctave + m_params.octaveCount - 1;
+
+    int midiPitchLimit = (1 + highestOctave) * 12 + 12; // C just beyond top
+    double midiPitchLimitFreq = Pitch::getFrequencyForPitch
+        (midiPitchLimit, 0, m_params.tuningFrequency);
+
+    // Max frequency is frequency of the MIDI pitch just beyond the
+    // top octave range (midiPitchLimit) minus one bin, then minus
+    // floor(bins per semitone / 2)
+    int bps = m_params.binsPerOctave / 12;
+    m_maxFrequency = midiPitchLimitFreq /
+        pow(2, (1.0 + floor(bps/2)) / m_params.binsPerOctave);
+
+    // Min frequency is frequency of midiPitchLimit lowered by the
+    // appropriate number of octaveCount.
+    m_minFrequency = midiPitchLimitFreq /
+        pow(2, m_params.octaveCount + 1);
+
+    CQParameters p
+        (params.sampleRate, m_minFrequency, m_maxFrequency, params.binsPerOctave);
+
+    p.q = params.q;
+    p.atomHopFactor = params.atomHopFactor;
+    p.threshold = params.threshold;
+    p.window = params.window;
+    
+    m_cq = new CQSpectrogram(p, CQSpectrogram::InterpolateLinear);
+}
+
+Chromagram::~Chromagram()
+{
+    delete m_cq;
+}
+
+bool
+Chromagram::isValid() const
+{
+    return m_cq->isValid();
+}
+
+int
+Chromagram::getColumnHop() const
+{
+    return m_cq->getColumnHop();
+}
+
+int
+Chromagram::getLatency() const
+{
+    return m_cq->getLatency();
+}
+
+string
+Chromagram::getBinName(int bin) const
+{
+    static const char *names[] = {
+        "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
+    };
+
+    float freq = m_cq->getBinFrequency(m_params.binsPerOctave - bin - 1);
+    int note = Pitch::getPitchForFrequency(freq, 0, m_params.tuningFrequency);
+    float nearestFreq =
+        Pitch::getFrequencyForPitch(note, 0, m_params.tuningFrequency);
+    
+    char name[40];
+    sprintf(name, "%d", bin);
+    if (fabs(freq - nearestFreq) < 0.01) {
+        return (name + std::string(" ") + names[note % 12]);
+    } else {
+        return (name);
+    }
+}
+
+CQBase::RealBlock
+Chromagram::process(const CQBase::RealSequence &data)
+{
+    return convert(m_cq->process(data));
+}
+
+CQBase::RealBlock
+Chromagram::getRemainingOutput()
+{
+    return convert(m_cq->getRemainingOutput());
+}
+
+CQBase::RealBlock
+Chromagram::convert(const CQBase::RealBlock &cqout)
+{    
+    CQBase::RealBlock chroma;
+
+    int width = cqout.size();
+
+    for (int i = 0; i < width; ++i) {
+
+        CQBase::RealSequence column(m_params.binsPerOctave, 0.);
+
+        // fold and invert to put low frequencies at the start
+
+        int thisHeight = cqout[i].size();
+
+	for (int j = 0; j < thisHeight; ++j) {
+	    column[m_params.binsPerOctave - (j % m_params.binsPerOctave) - 1]
+                += cqout[i][j];
+	}
+
+        chroma.push_back(column);
+    }
+
+    return chroma;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pitch.cpp	Thu Feb 05 09:53:06 2015 +0000
@@ -0,0 +1,63 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    Constant-Q library
+    Copyright (c) 2013-2014 Queen Mary, University of London
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#include "Pitch.h"
+
+#include <math.h>
+
+float
+Pitch::getFrequencyForPitch(int midiPitch,
+			    float centsOffset,
+			    float concertA)
+{
+    float p = float(midiPitch) + (centsOffset / 100);
+    return concertA * powf(2.0, (p - 69.0) / 12.0);
+}
+
+int
+Pitch::getPitchForFrequency(float frequency,
+			    float *centsOffsetReturn,
+			    float concertA)
+{
+    float p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0;
+
+    int midiPitch = int(p + 0.00001);
+    float centsOffset = (p - midiPitch) * 100.0;
+
+    if (centsOffset >= 50.0) {
+	midiPitch = midiPitch + 1;
+	centsOffset = -(100.0 - centsOffset);
+    }
+    
+    if (centsOffsetReturn) *centsOffsetReturn = centsOffset;
+    return midiPitch;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pitch.h	Thu Feb 05 09:53:06 2015 +0000
@@ -0,0 +1,52 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    Constant-Q library
+    Copyright (c) 2013-2014 Queen Mary, University of London
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of the Centre for
+    Digital Music; Queen Mary, University of London; and Chris Cannam
+    shall not be used in advertising or otherwise to promote the sale,
+    use or other dealings in this Software without prior written
+    authorization.
+*/
+
+#ifndef _PITCH_H_
+#define _PITCH_H_
+
+/**
+ * Convert between musical pitch (i.e. MIDI pitch number) and
+ * fundamental frequency.
+ */
+class Pitch
+{
+public:
+    static float getFrequencyForPitch(int midiPitch,
+				      float centsOffset = 0,
+				      float concertA = 440.0);
+
+    static int getPitchForFrequency(float frequency,
+				    float *centsOffsetReturn = 0,
+				    float concertA = 440.0);
+};
+
+
+#endif
--- a/vamp/CQChromaVamp.cpp	Wed Jan 14 18:00:34 2015 +0000
+++ b/vamp/CQChromaVamp.cpp	Thu Feb 05 09:53:06 2015 +0000
@@ -31,12 +31,9 @@
 
 #include "CQChromaVamp.h"
 
-#include "cq/CQSpectrogram.h"
-
-#include "Pitch.h"
+#include "cq/Chromagram.h"
 
 #include <algorithm>
-#include <cstdio>
 
 using std::string;
 using std::vector;
@@ -54,9 +51,7 @@
     m_octaveCount(defaultOctaveCount),
     m_tuningFrequency(defaultTuningFrequency),
     m_bpo(defaultBPO),
-    m_cq(0),
-    m_maxFrequency(0),
-    m_minFrequency(0),
+    m_chroma(0),
     m_haveStartTime(false),
     m_columnCount(0)
 {
@@ -64,7 +59,7 @@
 
 CQChromaVamp::~CQChromaVamp()
 {
-    delete m_cq;
+    delete m_chroma;
 }
 
 string
@@ -196,9 +191,9 @@
 bool
 CQChromaVamp::initialise(size_t channels, size_t stepSize, size_t blockSize)
 {
-    if (m_cq) {
-	delete m_cq;
-        m_cq = 0;
+    if (m_chroma) {
+	delete m_chroma;
+        m_chroma = 0;
     }
 
     if (channels < getMinChannelCount() ||
@@ -207,30 +202,9 @@
     m_stepSize = stepSize;
     m_blockSize = blockSize;
 
-    int highestOctave = m_lowestOctave + m_octaveCount - 1;
-
-    int midiPitchLimit = (1 + highestOctave) * 12 + 12; // C just beyond top
-    double midiPitchLimitFreq = 
-        Pitch::getFrequencyForPitch(midiPitchLimit, 0, m_tuningFrequency);
-
-    // Max frequency is frequency of the MIDI pitch just beyond the
-    // top octave range (midiPitchLimit) minus one bin, then minus
-    // floor(bins per semitone / 2)
-    int bps = m_bpo / 12;
-    m_maxFrequency = midiPitchLimitFreq / pow(2, (1.0 + floor(bps/2)) / m_bpo);
-
-    // Min frequency is frequency of midiPitchLimit lowered by the
-    // appropriate number of octaves.
-    m_minFrequency = midiPitchLimitFreq / pow(2, m_octaveCount + 1);
-
-//    cerr << "lowest octave: " << m_lowestOctave << ", highest octave: "
-//         << highestOctave << ", limit midi pitch: " << midiPitchLimit
-//         << ", min freq " << m_minFrequency << ", max freq " << m_maxFrequency
-//         << endl;
-
     reset();
 
-    if (!m_cq || !m_cq->isValid()) {
+    if (!m_chroma || !m_chroma->isValid()) {
         cerr << "CQVamp::initialise: Constant-Q parameters not valid! Not initialising" << endl;
         return false;
     }
@@ -241,9 +215,14 @@
 void
 CQChromaVamp::reset()
 {
-    delete m_cq;
-    CQParameters p(m_inputSampleRate, m_minFrequency, m_maxFrequency, m_bpo);
-    m_cq = new CQSpectrogram(p, CQSpectrogram::InterpolateLinear);
+    delete m_chroma;
+    Chromagram::Parameters p(m_inputSampleRate);
+    p.lowestOctave = m_lowestOctave;
+    p.octaveCount = m_octaveCount;
+    p.binsPerOctave = m_bpo;
+    p.tuningFrequency = m_tuningFrequency;
+
+    m_chroma = new Chromagram(p);
 
     m_haveStartTime = false;
     m_startTime = Vamp::RealTime::zeroTime;
@@ -265,10 +244,6 @@
 CQChromaVamp::OutputList
 CQChromaVamp::getOutputDescriptors() const
 {
-    static const char *names[] = {
-        "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
-    };
-
     OutputList list;
 
     OutputDescriptor d;
@@ -279,26 +254,16 @@
     d.hasFixedBinCount = true;
     d.binCount = m_bpo;
 
-    if (m_cq) {
-        char name[20];
+    if (m_chroma) {
         for (int i = 0; i < (int)d.binCount; ++i) {
-            float freq = m_cq->getBinFrequency(d.binCount - i - 1);
-            int note = Pitch::getPitchForFrequency(freq, 0, m_tuningFrequency);
-            float nearestFreq =
-                Pitch::getFrequencyForPitch(note, 0, m_tuningFrequency);
-            sprintf(name, "%d", i);
-            if (fabs(freq - nearestFreq) < 0.01) {
-                d.binNames.push_back(name + std::string(" ") + names[note % 12]);
-            } else {
-                d.binNames.push_back(name);
-            }
+            d.binNames.push_back(m_chroma->getBinName(i));
         }
     }
 
     d.hasKnownExtents = false;
     d.isQuantized = false;
     d.sampleType = OutputDescriptor::FixedSampleRate;
-    d.sampleRate = m_inputSampleRate / (m_cq ? m_cq->getColumnHop() : 256);
+    d.sampleRate = m_inputSampleRate / (m_chroma ? m_chroma->getColumnHop() : 256);
     list.push_back(d);
 
     return list;
@@ -308,7 +273,7 @@
 CQChromaVamp::process(const float *const *inputBuffers,
                       Vamp::RealTime timestamp)
 {
-    if (!m_cq) {
+    if (!m_chroma) {
 	cerr << "ERROR: CQChromaVamp::process: "
 	     << "Plugin has not been initialised"
 	     << endl;
@@ -323,40 +288,32 @@
     vector<double> data;
     for (int i = 0; i < m_blockSize; ++i) data.push_back(inputBuffers[0][i]);
     
-    vector<vector<double> > cqout = m_cq->process(data);
-    return convertToFeatures(cqout);
+    vector<vector<double> > chromaout = m_chroma->process(data);
+    return convertToFeatures(chromaout);
 }
 
 CQChromaVamp::FeatureSet
 CQChromaVamp::getRemainingFeatures()
 {
-    vector<vector<double> > cqout = m_cq->getRemainingOutput();
-    return convertToFeatures(cqout);
+    vector<vector<double> > chromaout = m_chroma->getRemainingOutput();
+    return convertToFeatures(chromaout);
 }
 
 CQChromaVamp::FeatureSet
-CQChromaVamp::convertToFeatures(const vector<vector<double> > &cqout)
+CQChromaVamp::convertToFeatures(const vector<vector<double> > &chromaout)
 {
     FeatureSet returnFeatures;
 
-    int width = cqout.size();
+    int width = chromaout.size();
 
     for (int i = 0; i < width; ++i) {
 
-	vector<float> column(m_bpo, 0.f);
-
-        // fold and invert to put low frequencies at the start
-
-        int thisHeight = cqout[i].size();
-
-	for (int j = 0; j < thisHeight; ++j) {
-	    column[m_bpo - (j % m_bpo) - 1] += cqout[i][j];
-	}
+	vector<float> column(chromaout[i].begin(), chromaout[i].end());
 
 	Feature feature;
 	feature.hasTimestamp = true;
         feature.timestamp = m_startTime + Vamp::RealTime::frame2RealTime
-            (m_columnCount * m_cq->getColumnHop() - m_cq->getLatency(),
+            (m_columnCount * m_chroma->getColumnHop() - m_chroma->getLatency(),
              m_inputSampleRate);
 	feature.values = column;
 	feature.label = "";
--- a/vamp/CQChromaVamp.h	Wed Jan 14 18:00:34 2015 +0000
+++ b/vamp/CQChromaVamp.h	Thu Feb 05 09:53:06 2015 +0000
@@ -34,7 +34,7 @@
 
 #include <vamp-sdk/Plugin.h>
 
-class CQSpectrogram;
+class Chromagram;
 
 class CQChromaVamp : public Vamp::Plugin
 {
@@ -74,9 +74,7 @@
     float m_tuningFrequency;
     int m_bpo;
 
-    CQSpectrogram *m_cq;
-    float m_maxFrequency;
-    float m_minFrequency;
+    Chromagram *m_chroma;
     int m_stepSize;
     int m_blockSize;
 
--- a/vamp/Pitch.cpp	Wed Jan 14 18:00:34 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-/*
-    Constant-Q library
-    Copyright (c) 2013-2014 Queen Mary, University of London
-
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and Chris Cannam
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#include "Pitch.h"
-
-#include <math.h>
-
-float
-Pitch::getFrequencyForPitch(int midiPitch,
-			    float centsOffset,
-			    float concertA)
-{
-    float p = float(midiPitch) + (centsOffset / 100);
-    return concertA * powf(2.0, (p - 69.0) / 12.0);
-}
-
-int
-Pitch::getPitchForFrequency(float frequency,
-			    float *centsOffsetReturn,
-			    float concertA)
-{
-    float p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0;
-
-    int midiPitch = int(p + 0.00001);
-    float centsOffset = (p - midiPitch) * 100.0;
-
-    if (centsOffset >= 50.0) {
-	midiPitch = midiPitch + 1;
-	centsOffset = -(100.0 - centsOffset);
-    }
-    
-    if (centsOffsetReturn) *centsOffsetReturn = centsOffset;
-    return midiPitch;
-}
-
--- a/vamp/Pitch.h	Wed Jan 14 18:00:34 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-/*
-    Constant-Q library
-    Copyright (c) 2013-2014 Queen Mary, University of London
-
-    Permission is hereby granted, free of charge, to any person
-    obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without
-    restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies
-    of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    Except as contained in this notice, the names of the Centre for
-    Digital Music; Queen Mary, University of London; and Chris Cannam
-    shall not be used in advertising or otherwise to promote the sale,
-    use or other dealings in this Software without prior written
-    authorization.
-*/
-
-#ifndef _PITCH_H_
-#define _PITCH_H_
-
-/**
- * Convert between musical pitch (i.e. MIDI pitch number) and
- * fundamental frequency.
- */
-class Pitch
-{
-public:
-    static float getFrequencyForPitch(int midiPitch,
-				      float centsOffset = 0,
-				      float concertA = 440.0);
-
-    static int getPitchForFrequency(float frequency,
-				    float *centsOffsetReturn = 0,
-				    float concertA = 440.0);
-};
-
-
-#endif