summaryrefslogtreecommitdiff
path: root/libs/qm-dsp/dsp/chromagram/Chromagram.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/qm-dsp/dsp/chromagram/Chromagram.cpp')
-rw-r--r--libs/qm-dsp/dsp/chromagram/Chromagram.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/libs/qm-dsp/dsp/chromagram/Chromagram.cpp b/libs/qm-dsp/dsp/chromagram/Chromagram.cpp
new file mode 100644
index 0000000000..014e37b55f
--- /dev/null
+++ b/libs/qm-dsp/dsp/chromagram/Chromagram.cpp
@@ -0,0 +1,181 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ QM DSP Library
+
+ Centre for Digital Music, Queen Mary, University of London.
+ This file 2005-2006 Christian Landone.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#include <iostream>
+#include <cmath>
+#include "maths/MathUtilities.h"
+#include "Chromagram.h"
+
+//----------------------------------------------------------------------------
+
+Chromagram::Chromagram( ChromaConfig Config ) :
+ m_skGenerated(false)
+{
+ initialise( Config );
+}
+
+int Chromagram::initialise( ChromaConfig Config )
+{
+ m_FMin = Config.min; // min freq
+ m_FMax = Config.max; // max freq
+ m_BPO = Config.BPO; // bins per octave
+ m_normalise = Config.normalise; // if frame normalisation is required
+
+ // No. of constant Q bins
+ m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
+
+ // Create array for chroma result
+ m_chromadata = new double[ m_BPO ];
+
+ // Create Config Structure for ConstantQ operator
+ CQConfig ConstantQConfig;
+
+ // Populate CQ config structure with parameters
+ // inherited from the Chroma config
+ ConstantQConfig.FS = Config.FS;
+ ConstantQConfig.min = m_FMin;
+ ConstantQConfig.max = m_FMax;
+ ConstantQConfig.BPO = m_BPO;
+ ConstantQConfig.CQThresh = Config.CQThresh;
+
+ // Initialise ConstantQ operator
+ m_ConstantQ = new ConstantQ( ConstantQConfig );
+
+ // Initialise working arrays
+ m_frameSize = m_ConstantQ->getfftlength();
+ m_hopSize = m_ConstantQ->gethop();
+
+ // Initialise FFT object
+ m_FFT = new FFTReal(m_frameSize);
+
+ m_FFTRe = new double[ m_frameSize ];
+ m_FFTIm = new double[ m_frameSize ];
+ m_CQRe = new double[ m_uK ];
+ m_CQIm = new double[ m_uK ];
+
+ m_window = 0;
+ m_windowbuf = 0;
+
+ return 1;
+}
+
+Chromagram::~Chromagram()
+{
+ deInitialise();
+}
+
+int Chromagram::deInitialise()
+{
+ delete[] m_windowbuf;
+ delete m_window;
+
+ delete [] m_chromadata;
+
+ delete m_FFT;
+
+ delete m_ConstantQ;
+
+ delete [] m_FFTRe;
+ delete [] m_FFTIm;
+ delete [] m_CQRe;
+ delete [] m_CQIm;
+ return 1;
+}
+
+//----------------------------------------------------------------------------------
+// returns the absolute value of complex number xx + i*yy
+double Chromagram::kabs(double xx, double yy)
+{
+ double ab = sqrt(xx*xx + yy*yy);
+ return(ab);
+}
+//-----------------------------------------------------------------------------------
+
+
+void Chromagram::unityNormalise(double *src)
+{
+ double min, max;
+
+ double val = 0;
+
+ MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
+
+ for( unsigned int i = 0; i < m_BPO; i++ )
+ {
+ val = src[ i ] / max;
+
+ src[ i ] = val;
+ }
+}
+
+
+double* Chromagram::process( const double *data )
+{
+ if (!m_skGenerated) {
+ // Generate CQ Kernel
+ m_ConstantQ->sparsekernel();
+ m_skGenerated = true;
+ }
+
+ if (!m_window) {
+ m_window = new Window<double>(HammingWindow, m_frameSize);
+ m_windowbuf = new double[m_frameSize];
+ }
+
+ for (int i = 0; i < m_frameSize; ++i) {
+ m_windowbuf[i] = data[i];
+ }
+ m_window->cut(m_windowbuf);
+
+ // FFT of current frame
+ m_FFT->process(false, m_windowbuf, m_FFTRe, m_FFTIm);
+
+ return process(m_FFTRe, m_FFTIm);
+}
+
+double* Chromagram::process( const double *real, const double *imag )
+{
+ if (!m_skGenerated) {
+ // Generate CQ Kernel
+ m_ConstantQ->sparsekernel();
+ m_skGenerated = true;
+ }
+
+ // initialise chromadata to 0
+ for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
+
+ double cmax = 0.0;
+ double cval = 0;
+
+ // Calculate ConstantQ frame
+ m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
+
+ // add each octave of cq data into Chromagram
+ const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
+ for (unsigned octave = 0; octave <= octaves; octave++)
+ {
+ unsigned firstBin = octave*m_BPO;
+ for (unsigned i = 0; i < m_BPO; i++)
+ {
+ m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
+ }
+ }
+
+ MathUtilities::normalise(m_chromadata, m_BPO, m_normalise);
+
+ return m_chromadata;
+}
+
+