1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
6 Centre for Digital Music, Queen Mary, University of London.
7 This file 2005-2006 Christian Landone.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
18 #include "maths/MathUtilities.h"
19 #include "Chromagram.h"
21 //----------------------------------------------------------------------------
23 Chromagram::Chromagram( ChromaConfig Config ) :
29 int Chromagram::initialise( ChromaConfig Config )
31 m_FMin = Config.min; // min freq
32 m_FMax = Config.max; // max freq
33 m_BPO = Config.BPO; // bins per octave
34 m_normalise = Config.normalise; // if frame normalisation is required
36 // No. of constant Q bins
37 m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
39 // Create array for chroma result
40 m_chromadata = new double[ m_BPO ];
42 // Create Config Structure for ConstantQ operator
43 CQConfig ConstantQConfig;
45 // Populate CQ config structure with parameters
46 // inherited from the Chroma config
47 ConstantQConfig.FS = Config.FS;
48 ConstantQConfig.min = m_FMin;
49 ConstantQConfig.max = m_FMax;
50 ConstantQConfig.BPO = m_BPO;
51 ConstantQConfig.CQThresh = Config.CQThresh;
53 // Initialise ConstantQ operator
54 m_ConstantQ = new ConstantQ( ConstantQConfig );
56 // Initialise working arrays
57 m_frameSize = m_ConstantQ->getfftlength();
58 m_hopSize = m_ConstantQ->gethop();
60 // Initialise FFT object
61 m_FFT = new FFTReal(m_frameSize);
63 m_FFTRe = new double[ m_frameSize ];
64 m_FFTIm = new double[ m_frameSize ];
65 m_CQRe = new double[ m_uK ];
66 m_CQIm = new double[ m_uK ];
74 Chromagram::~Chromagram()
79 int Chromagram::deInitialise()
84 delete [] m_chromadata;
97 //----------------------------------------------------------------------------------
98 // returns the absolute value of complex number xx + i*yy
99 double Chromagram::kabs(double xx, double yy)
101 double ab = sqrt(xx*xx + yy*yy);
104 //-----------------------------------------------------------------------------------
107 void Chromagram::unityNormalise(double *src)
113 MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
115 for( unsigned int i = 0; i < m_BPO; i++ )
117 val = src[ i ] / max;
124 double* Chromagram::process( const double *data )
126 if (!m_skGenerated) {
127 // Generate CQ Kernel
128 m_ConstantQ->sparsekernel();
129 m_skGenerated = true;
133 m_window = new Window<double>(HammingWindow, m_frameSize);
134 m_windowbuf = new double[m_frameSize];
137 for (int i = 0; i < m_frameSize; ++i) {
138 m_windowbuf[i] = data[i];
140 m_window->cut(m_windowbuf);
142 // FFT of current frame
143 m_FFT->process(false, m_windowbuf, m_FFTRe, m_FFTIm);
145 return process(m_FFTRe, m_FFTIm);
148 double* Chromagram::process( const double *real, const double *imag )
150 if (!m_skGenerated) {
151 // Generate CQ Kernel
152 m_ConstantQ->sparsekernel();
153 m_skGenerated = true;
156 // initialise chromadata to 0
157 for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
162 // Calculate ConstantQ frame
163 m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
165 // add each octave of cq data into Chromagram
166 const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
167 for (unsigned octave = 0; octave <= octaves; octave++)
169 unsigned firstBin = octave*m_BPO;
170 for (unsigned i = 0; i < m_BPO; i++)
172 m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
176 MathUtilities::normalise(m_chromadata, m_BPO, m_normalise);