changeset 21:d695fc2baa91

* Turning key-mode plugin into a generic key detection plugin, and attempting to debug it
author Chris Cannam <c.cannam@qmul.ac.uk>
date Mon, 22 Jan 2007 17:32:40 +0000
parents 1f1881046b0c
children 6d014fb538db
files libmain.cpp plugins/BeatDetect.cpp plugins/GetModePlugin.cpp plugins/GetModePlugin.h plugins/KeyDetect.cpp plugins/KeyDetect.h qm-vamp-plugins.cat qm-vamp-plugins.pro
diffstat 8 files changed, 452 insertions(+), 289 deletions(-) [+]
line wrap: on
line diff
--- a/libmain.cpp	Tue Dec 12 10:34:53 2006 +0000
+++ b/libmain.cpp	Mon Jan 22 17:32:40 2007 +0000
@@ -14,13 +14,13 @@
 #include "plugins/ChromagramPlugin.h"
 #include "plugins/ConstantQSpectrogram.h"
 #include "plugins/TonalChangeDetect.h"
-#include "plugins/GetModePlugin.h"
+#include "plugins/KeyDetect.h"
 
 static Vamp::PluginAdapter<BeatDetector> beatDetectorAdapter;
 static Vamp::PluginAdapter<ChromagramPlugin> chromagramPluginAdapter;
 static Vamp::PluginAdapter<ConstantQSpectrogram> constantQAdapter;
 static Vamp::PluginAdapter<TonalChangeDetect> tonalChangeDetectorAdapter;
-static Vamp::PluginAdapter<GetModePlugin> keyModeAdapter;
+static Vamp::PluginAdapter<KeyDetector> keyDetectorAdapter;
 
 const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int index)
 {
@@ -29,7 +29,7 @@
     case  1: return chromagramPluginAdapter.getDescriptor();
     case  2: return constantQAdapter.getDescriptor();
     case  3: return tonalChangeDetectorAdapter.getDescriptor();
-    case  4: return keyModeAdapter.getDescriptor();
+    case  4: return keyDetectorAdapter.getDescriptor();
     default: return 0;
     }
 }
--- a/plugins/BeatDetect.cpp	Tue Dec 12 10:34:53 2006 +0000
+++ b/plugins/BeatDetect.cpp	Mon Jan 22 17:32:40 2007 +0000
@@ -61,7 +61,7 @@
 string
 BeatDetector::getDescription() const
 {
-    return "Tempo Tracker";
+    return "Beat Tracker";
 }
 
 string
--- a/plugins/GetModePlugin.cpp	Tue Dec 12 10:34:53 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Vamp
-
-    An API for audio analysis and feature extraction plugins.
-
-    Centre for Digital Music, Queen Mary, University of London.
-    Copyright 2006 Chris Cannam.
-  
-    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 AUTHORS 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 "GetModePlugin.h"
-
-using std::string;
-using std::vector;
-//using std::cerr;
-using std::endl;
-
-#include <cmath>
-
-
-GetModePlugin::GetModePlugin(float inputSampleRate) :
-    Plugin(inputSampleRate),
-    m_stepSize(0),
-    m_blockSize(32768),
-    m_GetMode(0),
-    m_InputFrame(0),
-    m_BlockandHopSize(0)
-{
-    m_BlockandHopSize= 32768;
-}
-
-GetModePlugin::~GetModePlugin()
-{
-	if( m_GetMode )
-	{
-		delete m_GetMode;
-		m_GetMode = 0;
-	}
-
-	if( m_InputFrame )
-	{
-		delete [] m_InputFrame;
-		m_InputFrame = 0;
-	}
-}
-
-string
-GetModePlugin::getName() const
-{
-    return "qm-keymode";
-}
-
-string
-GetModePlugin::getDescription() const
-{
-    return "Key Mode";
-}
-
-string
-GetModePlugin::getMaker() const
-{
-    return "Katy Noland and Christian Landone";
-}
-
-int
-GetModePlugin::getPluginVersion() const
-{
-    return 2;
-}
-
-string
-GetModePlugin::getCopyright() const
-{
-    return "Centre for Digital Music QMUL";
-}
-
-bool
-GetModePlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
-{
-    if (channels < getMinChannelCount() ||
-	channels > getMaxChannelCount()) return false;
-
-    m_stepSize = stepSize;
-    m_blockSize = blockSize;
-
-    if( stepSize != m_BlockandHopSize || blockSize != m_BlockandHopSize )
-        return false;
-
-    m_GetMode = new GetKeyMode( 10, 10 );
-    
-    m_InputFrame = new double[m_BlockandHopSize];
-	
-    return true;
-}
-
-void
-GetModePlugin::reset()
-{
-    for( unsigned int i = 0; i < m_BlockandHopSize; i++ )
-    {
-        m_InputFrame[ i ] = 0.0;
-    }
-}
-
-
-GetModePlugin::OutputList
-GetModePlugin::getOutputDescriptors() const
-{
-    OutputList list;
-
-    OutputDescriptor d;
-    d.name = "mode";
-    d.unit = "";
-    d.description = "Key Mode";
-    d.hasFixedBinCount = true;
-    d.binCount = 1;
-    d.hasKnownExtents = true;
-    d.isQuantized = true;
-    d.minValue = 0;
-    d.maxValue = 1;
-    d.quantizeStep = 1;
-    d.binNames.push_back("Major = 0, Minor = 1");
-    d.sampleType = OutputDescriptor::OneSamplePerStep;
-    list.push_back(d);
-
-    return list;
-}
-
-GetModePlugin::FeatureSet
-GetModePlugin::process(const float *const *inputBuffers,
-                       Vamp::RealTime)
-{
-    if (m_stepSize == 0) {
-	return FeatureSet();
-    }
-
-    FeatureSet returnFeatures;
-
-	for( unsigned int i = 0 ; i < m_BlockandHopSize; i++ )
-	{
-		m_InputFrame[i] = (double)inputBuffers[0][i];
-	}
-
-
-	int minor = m_GetMode->isModeMinor(m_GetMode->process( m_InputFrame ));
-
-	Feature feature;
-	feature.hasTimestamp = false;
-
-	feature.values.push_back((float)minor);
-	returnFeatures[0].push_back(feature);
-        feature.values.clear();
-
-    return returnFeatures;
-}
-
-GetModePlugin::FeatureSet
-GetModePlugin::getRemainingFeatures()
-{
-    return FeatureSet();
-}
-
-
-size_t
-GetModePlugin::getPreferredStepSize() const
-{
-    return 0;
-}
-
-size_t
-GetModePlugin::getPreferredBlockSize() const
-{
-    return 32768;
-}
-
--- a/plugins/GetModePlugin.h	Tue Dec 12 10:34:53 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Vamp
-
-    An API for audio analysis and feature extraction plugins.
-
-    Centre for Digital Music, Queen Mary, University of London.
-    Copyright 2006 Chris Cannam.
-  
-    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 AUTHORS 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 _GETMODE_PLUGIN_H_
-#define _GETMODE_PLUGIN_H_
-
-#include <vamp-sdk/Plugin.h>
-
-#include <dsp/keydetection/GetKeyMode.h>
-
-class GetModePlugin : public Vamp::Plugin
-{
-public:
-    GetModePlugin(float inputSampleRate);
-    virtual ~GetModePlugin();
-
-    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
-    void reset();
-
-    InputDomain getInputDomain() const { return TimeDomain; }
-
-    std::string getName() const;
-    std::string getDescription() const;
-    std::string getMaker() const;
-    int getPluginVersion() const;
-    std::string getCopyright() const;
-
-    OutputList getOutputDescriptors() const;
-
-    FeatureSet process(const float *const *inputBuffers,
-                       Vamp::RealTime timestamp);
-
-    FeatureSet getRemainingFeatures();
-
-    size_t getPreferredStepSize() const;
-    size_t getPreferredBlockSize() const;
-
-protected:
-    size_t m_stepSize;
-    size_t m_blockSize;
-
-    GetKeyMode* m_GetMode;
-    double* m_InputFrame;
-    unsigned int m_BlockandHopSize;
-};
-
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/KeyDetect.cpp	Mon Jan 22 17:32:40 2007 +0000
@@ -0,0 +1,356 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 QMUL.
+  
+    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 AUTHORS 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 "KeyDetect.h"
+
+using std::string;
+using std::vector;
+//using std::cerr;
+using std::endl;
+
+#include <cmath>
+
+
+KeyDetector::KeyDetector(float inputSampleRate) :
+    Plugin(inputSampleRate),
+    m_stepSize(0),
+    m_blockSize(0),
+    m_tuningFrequency(440),
+    m_length(10),
+    m_getKeyMode(0),
+    m_inputFrame(0),
+    m_prevKey(-1)
+{
+}
+
+KeyDetector::~KeyDetector()
+{
+    delete m_getKeyMode;
+    if ( m_inputFrame ) {
+        delete [] m_inputFrame;
+    }
+}
+
+string
+KeyDetector::getName() const
+{
+    return "qm-keydetector";
+}
+
+string
+KeyDetector::getDescription() const
+{
+    return "Key Detector";
+}
+
+string
+KeyDetector::getMaker() const
+{
+    return "Katy Noland and Christian Landone, Queen Mary, University of London";
+}
+
+int
+KeyDetector::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+KeyDetector::getCopyright() const
+{
+    return "Copyright (c) 2006-2007 - All Rights Reserved";
+}
+
+KeyDetector::ParameterList
+KeyDetector::getParameterDescriptors() const
+{
+    ParameterList list;
+
+    ParameterDescriptor desc;
+    desc.name = "tuning";
+    desc.description = "Tuning Frequency";
+    desc.unit = "Hz";
+    desc.minValue = 420;
+    desc.maxValue = 460;
+    desc.defaultValue = 440;
+    desc.isQuantized = false;
+    list.push_back(desc);
+    
+    desc.name = "length";
+    desc.description = "Window Length";
+    desc.unit = "chroma frames";
+    desc.minValue = 1;
+    desc.maxValue = 30;
+    desc.defaultValue = 10;
+    desc.isQuantized = true;
+    desc.quantizeStep = 1;
+    list.push_back(desc);
+
+    return list;
+}
+
+float
+KeyDetector::getParameter(std::string param) const
+{
+    if (param == "tuning") {
+        return m_tuningFrequency;
+    }
+    if (param == "length") {
+        return m_length;
+    }
+    std::cerr << "WARNING: KeyDetect::getParameter: unknown parameter \""
+              << param << "\"" << std::endl;
+    return 0.0;
+}
+
+void
+KeyDetector::setParameter(std::string param, float value)
+{
+    if (param == "tuning") {
+        m_tuningFrequency = value;
+    } else if (param == "length") {
+        m_length = int(value + 0.1);
+    } else {
+        std::cerr << "WARNING: KeyDetect::setParameter: unknown parameter \""
+                  << param << "\"" << std::endl;
+    }
+}
+
+bool
+KeyDetector::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (m_getKeyMode) {
+        delete m_getKeyMode;
+        m_getKeyMode = 0;
+    }
+
+    if (channels < getMinChannelCount() ||
+	channels > getMaxChannelCount()) return false;
+
+    m_getKeyMode = new GetKeyMode(int(m_inputSampleRate + 0.1),
+                                  m_tuningFrequency,
+                                  m_length, m_length);
+
+    m_stepSize = m_getKeyMode->getHopSize();
+    m_blockSize = m_getKeyMode->getBlockSize();
+
+    if (stepSize != m_stepSize || blockSize != m_blockSize) {
+        std::cerr << "KeyDetector::initialise: step/block sizes "
+                  << stepSize << "/" << blockSize << " differ from required "
+                  << m_stepSize << "/" << m_blockSize << std::endl;
+        delete m_getKeyMode;
+        m_getKeyMode = 0;
+        return false;
+    }
+
+    m_inputFrame = new double[m_blockSize];
+
+    m_prevKey = -1;
+	
+    return true;
+}
+
+void
+KeyDetector::reset()
+{
+    if (m_getKeyMode) {
+        delete m_getKeyMode;
+        m_getKeyMode = new GetKeyMode(int(m_inputSampleRate + 0.1),
+                                      m_tuningFrequency,
+                                      m_length, m_length);
+    }
+
+    if (m_inputFrame) {
+        for( unsigned int i = 0; i < m_blockSize; i++ ) {
+            m_inputFrame[ i ] = 0.0;
+        }
+    }
+
+    m_prevKey = -1;
+}
+
+
+KeyDetector::OutputList
+KeyDetector::getOutputDescriptors() const
+{
+    OutputList list;
+
+    OutputDescriptor d;
+    d.name = "tonic";
+    d.unit = "";
+    d.description = "Tonic Pitch";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.hasKnownExtents = true;
+    d.isQuantized = true;
+    d.minValue = 0;
+    d.maxValue = 11;
+    d.quantizeStep = 1;
+    d.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(d);
+
+    d.name = "mode";
+    d.unit = "";
+    d.description = "Key Mode";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.hasKnownExtents = true;
+    d.isQuantized = true;
+    d.minValue = 0;
+    d.maxValue = 1;
+    d.quantizeStep = 1;
+    d.binNames.push_back("Major = 0, Minor = 1");
+    d.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(d);
+
+    d.name = "key";
+    d.unit = "";
+    d.description = "Key";
+    d.hasFixedBinCount = true;
+    d.binCount = 1;
+    d.hasKnownExtents = true;
+    d.isQuantized = true;
+    d.minValue = 0;
+    d.maxValue = 23;
+    d.quantizeStep = 1;
+    d.sampleType = OutputDescriptor::OneSamplePerStep;
+    list.push_back(d);
+
+    return list;
+}
+
+KeyDetector::FeatureSet
+KeyDetector::process(const float *const *inputBuffers,
+                     Vamp::RealTime now)
+{
+    if (m_stepSize == 0) {
+	return FeatureSet();
+    }
+
+    FeatureSet returnFeatures;
+
+    for ( unsigned int i = 0 ; i < m_blockSize; i++ ) {
+        m_inputFrame[i] = (double)inputBuffers[0][i];
+    }
+
+//    int key = (m_getKeyMode->process(m_inputFrame) % 24);
+    int key = m_getKeyMode->process(m_inputFrame);
+    int minor = m_getKeyMode->isModeMinor(key);
+    int tonic = key;
+    if (tonic > 12) tonic -= 12;
+
+    int prevTonic = m_prevKey;
+    if (prevTonic > 12) prevTonic -= 12;
+
+    if (tonic != prevTonic) {
+        Feature feature;
+        feature.hasTimestamp = false;
+//        feature.timestamp = now;
+        feature.values.push_back((float)tonic);
+        feature.label = getKeyName(tonic);
+        returnFeatures[0].push_back(feature); // tonic
+    }
+
+    if (minor != (m_getKeyMode->isModeMinor(m_prevKey))) {
+        Feature feature;
+        feature.hasTimestamp = false;
+        feature.values.push_back((float)minor);
+        feature.label = (minor ? "Minor" : "Major");
+        returnFeatures[1].push_back(feature); // mode
+    }
+
+    if (key != m_prevKey) {
+        Feature feature;
+//        feature.hasTimestamp = true;
+        feature.hasTimestamp = false;
+//        feature.timestamp = now;
+        feature.values.push_back((float)key);
+        feature.label = std::string(getKeyName(tonic));
+        if (minor) feature.label += " minor";
+        else feature.label += " major";
+        returnFeatures[2].push_back(feature); // key
+    }
+
+    m_prevKey = key;
+
+    return returnFeatures;
+}
+
+KeyDetector::FeatureSet
+KeyDetector::getRemainingFeatures()
+{
+    return FeatureSet();
+}
+
+
+size_t
+KeyDetector::getPreferredStepSize() const
+{
+    if (!m_stepSize) {
+        GetKeyMode gkm(int(m_inputSampleRate + 0.1),
+                       m_tuningFrequency, m_length, m_length);
+        m_stepSize = gkm.getHopSize();
+        m_blockSize = gkm.getBlockSize();
+    }
+    return m_stepSize;
+}
+
+size_t
+KeyDetector::getPreferredBlockSize() const
+{
+    if (!m_blockSize) {
+        GetKeyMode gkm(int(m_inputSampleRate + 0.1),
+                       m_tuningFrequency, m_length, m_length);
+        m_stepSize = gkm.getHopSize();
+        m_blockSize = gkm.getBlockSize();
+    }
+    return m_blockSize;
+}
+
+const char *
+KeyDetector::getKeyName(int index)
+{
+    static const char *names[] = {
+        "C", "C# / Db", "D", "D# / Eb",
+        "E", "F", "F# / Gb", "G",
+        "G# / Ab", "A", "A# / Bb", "B"
+    };
+    if (index < 1 || index > 12) {
+        return "(unknown)";
+    }
+    return names[index - 1];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/KeyDetect.h	Mon Jan 22 17:32:40 2007 +0000
@@ -0,0 +1,89 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Vamp
+
+    An API for audio analysis and feature extraction plugins.
+
+    Centre for Digital Music, Queen Mary, University of London.
+    Copyright 2006-2007 QMUL.
+  
+    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 AUTHORS 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 _GETMODE_PLUGIN_H_
+#define _GETMODE_PLUGIN_H_
+
+#include <vamp-sdk/Plugin.h>
+
+#include <dsp/keydetection/GetKeyMode.h>
+
+class KeyDetector : public Vamp::Plugin
+{
+public:
+    KeyDetector(float inputSampleRate);
+    virtual ~KeyDetector();
+
+    bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
+
+    InputDomain getInputDomain() const { return TimeDomain; }
+
+    std::string getName() const;
+    std::string getDescription() const;
+    std::string getMaker() const;
+    int getPluginVersion() const;
+    std::string getCopyright() const;
+
+    ParameterList getParameterDescriptors() const;
+    float getParameter(std::string) const;
+    void setParameter(std::string, float);
+
+    OutputList getOutputDescriptors() const;
+
+    FeatureSet process(const float *const *inputBuffers,
+                       Vamp::RealTime timestamp);
+
+    FeatureSet getRemainingFeatures();
+
+    size_t getPreferredStepSize() const;
+    size_t getPreferredBlockSize() const;
+
+protected:
+    mutable size_t m_stepSize;
+    mutable size_t m_blockSize;
+    float m_tuningFrequency;
+    int m_length;
+
+    const char *getKeyName(int index);
+
+    GetKeyMode* m_getKeyMode;
+    double* m_inputFrame;
+    int m_prevKey;
+};
+
+
+#endif
--- a/qm-vamp-plugins.cat	Tue Dec 12 10:34:53 2006 +0000
+++ b/qm-vamp-plugins.cat	Mon Jan 22 17:32:40 2007 +0000
@@ -2,4 +2,4 @@
 vamp:qm-vamp-plugins:qm-chromagram::Visualisation
 vamp:qm-vamp-plugins:qm-constantq::Visualisation
 vamp:qm-vamp-plugins:qm-tonalchange::Key and Tonality
-vamp:qm-vamp-plugins:qm-keymode::Key and Tonality
+vamp:qm-vamp-plugins:qm-keydetector::Key and Tonality
--- a/qm-vamp-plugins.pro	Tue Dec 12 10:34:53 2006 +0000
+++ b/qm-vamp-plugins.pro	Mon Jan 22 17:32:40 2007 +0000
@@ -21,11 +21,11 @@
 HEADERS += plugins/BeatDetect.h \
            plugins/ChromagramPlugin.h \
            plugins/ConstantQSpectrogram.h \
-           plugins/GetModePlugin.h \
+           plugins/KeyDetect.h \
            plugins/TonalChangeDetect.h
 SOURCES += plugins/BeatDetect.cpp \
            plugins/ChromagramPlugin.cpp \
            plugins/ConstantQSpectrogram.cpp \
-           plugins/GetModePlugin.cpp \
+           plugins/KeyDetect.cpp \
            plugins/TonalChangeDetect.cpp \
            ./libmain.cpp