qm-dsp  1.8
Chromagram.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     QM DSP Library
00005 
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file 2005-2006 Christian Landone.
00008 
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include <iostream>
00017 #include <cmath>
00018 #include "maths/MathUtilities.h"
00019 #include "Chromagram.h"
00020 
00021 //----------------------------------------------------------------------------
00022 
00023 Chromagram::Chromagram( ChromaConfig Config ) :
00024     m_skGenerated(false)
00025 {
00026     initialise( Config );
00027 }
00028 
00029 int Chromagram::initialise( ChromaConfig Config )
00030 {       
00031     m_FMin = Config.min;                // min freq
00032     m_FMax = Config.max;                // max freq
00033     m_BPO  = Config.BPO;                // bins per octave
00034     m_normalise = Config.normalise;     // if frame normalisation is required
00035 
00036     // No. of constant Q bins
00037     m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0)); 
00038 
00039     // Create array for chroma result
00040     m_chromadata = new double[ m_BPO ];
00041 
00042     // Create Config Structure for ConstantQ operator
00043     CQConfig ConstantQConfig;
00044 
00045     // Populate CQ config structure with parameters
00046     // inherited from the Chroma config
00047     ConstantQConfig.FS   = Config.FS;
00048     ConstantQConfig.min = m_FMin;
00049     ConstantQConfig.max = m_FMax;
00050     ConstantQConfig.BPO = m_BPO;
00051     ConstantQConfig.CQThresh = Config.CQThresh;
00052         
00053     // Initialise ConstantQ operator
00054     m_ConstantQ = new ConstantQ( ConstantQConfig );
00055 
00056     // Initialise working arrays
00057     m_frameSize = m_ConstantQ->getfftlength();
00058     m_hopSize = m_ConstantQ->gethop();
00059 
00060     // Initialise FFT object    
00061     m_FFT = new FFTReal(m_frameSize);
00062 
00063     m_FFTRe = new double[ m_frameSize ];
00064     m_FFTIm = new double[ m_frameSize ];
00065     m_CQRe  = new double[ m_uK ];
00066     m_CQIm  = new double[ m_uK ];
00067 
00068     m_window = 0;
00069     m_windowbuf = 0;
00070 
00071     return 1;
00072 }
00073 
00074 Chromagram::~Chromagram()
00075 {
00076     deInitialise();
00077 }
00078 
00079 int Chromagram::deInitialise()
00080 {
00081     delete[] m_windowbuf;
00082     delete m_window;
00083 
00084     delete [] m_chromadata;
00085 
00086     delete m_FFT;
00087 
00088     delete m_ConstantQ;
00089 
00090     delete [] m_FFTRe;
00091     delete [] m_FFTIm;
00092     delete [] m_CQRe;
00093     delete [] m_CQIm;
00094     return 1;
00095 }
00096 
00097 //----------------------------------------------------------------------------------
00098 // returns the absolute value of complex number xx + i*yy
00099 double Chromagram::kabs(double xx, double yy)
00100 {
00101     double ab = sqrt(xx*xx + yy*yy);
00102     return(ab);
00103 }
00104 //-----------------------------------------------------------------------------------
00105 
00106 
00107 void Chromagram::unityNormalise(double *src)
00108 {
00109     double min, max;
00110 
00111     double val = 0;
00112 
00113     MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
00114 
00115     for( unsigned int i = 0; i < m_BPO; i++ )
00116     {
00117         val = src[ i ] / max;
00118 
00119         src[ i ] = val;
00120     }
00121 }
00122 
00123 
00124 double* Chromagram::process( const double *data )
00125 {
00126     if (!m_skGenerated) {
00127         // Generate CQ Kernel 
00128         m_ConstantQ->sparsekernel();
00129         m_skGenerated = true;
00130     }
00131 
00132     if (!m_window) {
00133         m_window = new Window<double>(HammingWindow, m_frameSize);
00134         m_windowbuf = new double[m_frameSize];
00135     }
00136 
00137     for (int i = 0; i < m_frameSize; ++i) {
00138         m_windowbuf[i] = data[i];
00139     }
00140     m_window->cut(m_windowbuf);
00141 
00142     m_FFT->forward(m_windowbuf, m_FFTRe, m_FFTIm);
00143 
00144     return process(m_FFTRe, m_FFTIm);
00145 }
00146 
00147 double* Chromagram::process( const double *real, const double *imag )
00148 {
00149     if (!m_skGenerated) {
00150         // Generate CQ Kernel 
00151         m_ConstantQ->sparsekernel();
00152         m_skGenerated = true;
00153     }
00154 
00155     // initialise chromadata to 0
00156     for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
00157 
00158     double cmax = 0.0;
00159     double cval = 0;
00160     // Calculate ConstantQ frame
00161     m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
00162         
00163     // add each octave of cq data into Chromagram
00164     const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
00165     for (unsigned octave = 0; octave <= octaves; octave++) 
00166     {
00167         unsigned firstBin = octave*m_BPO;
00168         for (unsigned i = 0; i < m_BPO; i++) 
00169         {
00170             m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
00171         }
00172     }
00173 
00174     MathUtilities::normalise(m_chromadata, m_BPO, m_normalise);
00175 
00176     return m_chromadata;
00177 }
00178 
00179