view dsp/chromagram/Chromagram.cpp @ 209:ccd2019190bf msvc

Some MSVC fixes, including (temporarily, probably) renaming the FFT source file to avoid getting it mixed up with the Vamp SDK one in our object dir
author Chris Cannam
date Thu, 01 Feb 2018 16:34:08 +0000
parents e4a57215ddee
children 50a97c8d52ed
line wrap: on
line source
/* -*- 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 = (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 (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);

    m_FFT->forward(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 (int i = 0; i < m_BPO; i++) m_chromadata[i] = 0;

    // Calculate ConstantQ frame
    m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
	
    // add each octave of cq data into Chromagram
    const int octaves = (int)floor(double( m_uK/m_BPO))-1;
    for (int octave = 0; octave <= octaves; octave++) 
    {
	int firstBin = octave*m_BPO;
	for (int 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;
}