changeset 509:3f0a96460c33

Switch to config-struct constructor; add frameOverlapFactor parameter
author Chris Cannam <cannam@all-day-breakfast.com>
date Thu, 06 Jun 2019 14:20:53 +0100
parents 855d862cf02b
children 2adcd94c2079
files dsp/keydetection/GetKeyMode.cpp dsp/keydetection/GetKeyMode.h
diffstat 2 files changed, 72 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/dsp/keydetection/GetKeyMode.cpp	Wed Jun 05 16:05:09 2019 +0100
+++ b/dsp/keydetection/GetKeyMode.cpp	Thu Jun 06 14:20:53 2019 +0100
@@ -16,6 +16,10 @@
 */
 
 #include "GetKeyMode.h"
+
+#include "dsp/rateconversion/Decimator.h"
+#include "dsp/chromagram/Chromagram.h"
+
 #include "maths/MathUtilities.h"
 #include "base/Pitch.h"
 
@@ -47,10 +51,10 @@
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,
-                        double hpcpAverage, double medianAverage ) :
-    m_hpcpAverage( hpcpAverage ),
-    m_medianAverage( medianAverage ),
+GetKeyMode::GetKeyMode(Config config) :
+    m_hpcpAverage(config.hpcpAverage),
+    m_medianAverage(config.medianAverage),
+    m_decimationFactor(config.decimationFactor),
     m_chrPointer(0),
     m_decimatedBuffer(0),
     m_chromaBuffer(0),
@@ -61,38 +65,41 @@
     m_sortedBuffer(0),
     m_keyStrengths(0)
 {
-    m_decimationFactor = 8;
-        
+    ChromaConfig chromaConfig;
+    
     // Chromagram configuration parameters
-    m_chromaConfig.normalise = MathUtilities::NormaliseUnitMax;
-    m_chromaConfig.FS = sampleRate / (double)m_decimationFactor;
-    if (m_chromaConfig.FS < 1) {
-        m_chromaConfig.FS = 1;
+    chromaConfig.normalise = MathUtilities::NormaliseUnitMax;
+    chromaConfig.FS = config.sampleRate / (double)m_decimationFactor;
+    if (chromaConfig.FS < 1) {
+        chromaConfig.FS = 1;
     }
 
     // Set C3 (= MIDI #48) as our base:
     // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc.
-    m_chromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency );
-    m_chromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency );
+    chromaConfig.min =
+        Pitch::getFrequencyForPitch( 48, 0, config.tuningFrequency );
+    chromaConfig.max =
+        Pitch::getFrequencyForPitch( 96, 0, config.tuningFrequency );
 
-    m_chromaConfig.BPO = kBinsPerOctave;
-    m_chromaConfig.CQThresh = 0.0054;
+    chromaConfig.BPO = kBinsPerOctave;
+    chromaConfig.CQThresh = 0.0054;
 
     // Chromagram inst.
-    m_chroma = new Chromagram( m_chromaConfig );
+    m_chroma = new Chromagram(chromaConfig);
 
     // Get calculated parameters from chroma object
     m_chromaFrameSize = m_chroma->getFrameSize();
+
     // override hopsize for this application
-    m_chromaHopSize = m_chromaFrameSize;
+    m_chromaHopSize = m_chromaFrameSize / config.frameOverlapFactor;
 
 //    std::cerr << "chroma frame size = " << m_ChromaFrameSize << ", decimation factor = " << m_DecimationFactor << " therefore block size = " << getBlockSize() << std::endl;
 
     // Chromagram average and estimated key median filter lengths
     m_chromaBufferSize = (int)ceil
-        (m_hpcpAverage * m_chromaConfig.FS / m_chromaFrameSize);
+        (m_hpcpAverage * chromaConfig.FS / m_chromaFrameSize);
     m_medianWinSize = (int)ceil
-        (m_medianAverage * m_chromaConfig.FS / m_chromaFrameSize);
+        (m_medianAverage * chromaConfig.FS / m_chromaFrameSize);
     
     // Reset counters
     m_bufferIndex = 0;
@@ -282,17 +289,6 @@
     return key;
 }
 
-
-bool GetKeyMode::isModeMinor( int key )
-{ 
-    return (key > 12);
-}
-
-int GetKeyMode::getChromaSize() 
-{ 
-    return kBinsPerOctave; 
-}
-
 double* GetKeyMode::getKeyStrengths() {
     int k;
 
--- a/dsp/keydetection/GetKeyMode.h	Wed Jun 05 16:05:09 2019 +0100
+++ b/dsp/keydetection/GetKeyMode.h	Thu Jun 06 14:20:53 2019 +0100
@@ -13,37 +13,64 @@
 #ifndef QM_DSP_GETKEYMODE_H
 #define QM_DSP_GETKEYMODE_H
 
-
-#include "dsp/rateconversion/Decimator.h"
-#include "dsp/chromagram/Chromagram.h"
-
+class Decimator;
+class Chromagram;
 
 class GetKeyMode  
 {
 public:
-    GetKeyMode( int sampleRate, float tuningFrequency,
-                double hpcpAverage, double medianAverage );
+    struct Config {
+        double sampleRate;
+        float tuningFrequency;
+        double hpcpAverage;
+        double medianAverage;
+        int frameOverlapFactor; // 1 = none (default, fast, but means
+                                // we skip a fair bit of input data);
+                                // 8 = normal chroma overlap
+        int decimationFactor;
+
+        Config(double _sampleRate, float _tuningFrequency) :
+            sampleRate(_sampleRate),
+            tuningFrequency(_tuningFrequency),
+            hpcpAverage(10),
+            medianAverage(10),
+            frameOverlapFactor(1),
+            decimationFactor(8) {
+        }
+    };
+    
+    GetKeyMode(Config config);
 
     virtual ~GetKeyMode();
 
-    int process( double* PCMData );
+    /**
+     * Process a single time-domain input sample frame of length
+     * getBlockSize(). Successive calls should provide overlapped data
+     * with an advance of getHopSize() between frames.
+     *
+     * Return a key index in the range 0-24, where 0 indicates no key
+     * detected, 1 is C major, and 13 is C minor.
+     */
+    int process(double *pcmData);
 
-    double krumCorr( const double *pDataNorm, const double *pProfileNorm, 
-                     int shiftProfile, int length );
+    /**
+     * Return a pointer to an internal 24-element array containing the
+     * correlation of the chroma vector generated in the last
+     * process() call against the stored key profiles for the 12 major
+     * and 12 minor keys, where index 0 is C major and 12 is C minor.
+     */
+    double *getKeyStrengths();
 
-    int getBlockSize() { return m_chromaFrameSize * m_decimationFactor; }
-    int getHopSize() { return m_chromaHopSize * m_decimationFactor; }
-
-    double* getChroma() { return m_chrPointer; }
-    int getChromaSize();
-
-    double* getMeanHPCP() { return m_meanHPCP; }
-
-    double* getKeyStrengths();
-
-    bool isModeMinor( int key ); 
+    int getBlockSize() {
+        return m_chromaFrameSize * m_decimationFactor;
+    }
+    int getHopSize() {
+        return m_chromaHopSize * m_decimationFactor;
+    }
 
 protected:
+    double krumCorr(const double *pDataNorm, const double *pProfileNorm, 
+                    int shiftProfile, int length);
 
     double m_hpcpAverage;
     double m_medianAverage;
@@ -52,9 +79,6 @@
     // Decimator (fixed)
     Decimator* m_decimator;
 
-    // Chroma configuration
-    ChromaConfig m_chromaConfig;
-
     // Chromagram object
     Chromagram* m_chroma;