changeset 13:7680cc4c0073

* Tidying - made length of array variables type size_t and for loops unsigned int, where index > 0. * Window length parameter is now a dropdown box.
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Wed, 13 Aug 2014 14:18:00 +0100
parents d58409ecd720
children c11367df624d
files FIRFilter.cpp FIRFilter.h NoveltyCurve.cpp NoveltyCurve.h Spectrogram.cpp Spectrogram.h Tempogram.cpp Tempogram.h WindowFunction.cpp WindowFunction.h
diffstat 10 files changed, 243 insertions(+), 230 deletions(-) [+]
line wrap: on
line diff
--- a/FIRFilter.cpp	Wed Aug 13 10:47:39 2014 +0100
+++ b/FIRFilter.cpp	Wed Aug 13 14:18:00 2014 +0100
@@ -11,19 +11,19 @@
 using namespace std;
 using Vamp::FFT;
 
-FIRFilter::FIRFilter(const unsigned int lengthInput, const unsigned int numberOfCoefficients) :
+FIRFilter::FIRFilter(const size_t &lengthInput, const size_t &numberOfCoefficients) :
     m_lengthInput(lengthInput),
     m_numberOfCoefficients(numberOfCoefficients),
-    fftInput(0),
-    fftCoefficients(0),
-    fftReal1(0),
-    fftImag1(0),
-    fftReal2(0),
-    fftImag2(0),
-    fftFilteredReal(0),
-    fftFilteredImag(0),
-    fftOutputReal(0),
-    fftOutputImag(0)
+    m_pFftInput(0),
+    m_pFftCoefficients(0),
+    m_pFftReal1(0),
+    m_pFftImag1(0),
+    m_pFftReal2(0),
+    m_pFftImag2(0),
+    m_pFftFilteredReal(0),
+    m_pFftFilteredImag(0),
+    m_pFftOutputReal(0),
+    m_pFftOutputImag(0)
 {
     initialise();
 }
@@ -40,44 +40,45 @@
     //next power of 2
     m_lengthFIRFFT = pow(2,(ceil(log2(m_lengthInput+m_numberOfCoefficients-1))));
     
-    fftInput = new double[m_lengthFIRFFT];
-    fftCoefficients = new double[m_lengthFIRFFT];
-    fftReal1 = new double[m_lengthFIRFFT];
-    fftImag1 = new double[m_lengthFIRFFT];
-    fftReal2 = new double[m_lengthFIRFFT];
-    fftImag2 = new double[m_lengthFIRFFT];
-    fftFilteredReal = new double[m_lengthFIRFFT];
-    fftFilteredImag = new double[m_lengthFIRFFT];
-    fftOutputReal = new double[m_lengthFIRFFT];
-    fftOutputImag = new double[m_lengthFIRFFT];
+    m_pFftInput = new double[m_lengthFIRFFT];
+    m_pFftCoefficients = new double[m_lengthFIRFFT];
+    m_pFftReal1 = new double[m_lengthFIRFFT];
+    m_pFftImag1 = new double[m_lengthFIRFFT];
+    m_pFftReal2 = new double[m_lengthFIRFFT];
+    m_pFftImag2 = new double[m_lengthFIRFFT];
+    m_pFftFilteredReal = new double[m_lengthFIRFFT];
+    m_pFftFilteredImag = new double[m_lengthFIRFFT];
+    m_pFftOutputReal = new double[m_lengthFIRFFT];
+    m_pFftOutputImag = new double[m_lengthFIRFFT];
     
-    for(int i = 0; i < m_lengthFIRFFT; i++){
-        fftInput[i] = fftCoefficients[i] = fftReal1[i] = fftImag1[i] = fftReal2[i] = fftImag2[i] = fftFilteredReal[i] = fftFilteredImag[i] = fftOutputReal[i] = fftOutputImag[i] = 0.0;
+    for(unsigned int i = 0; i < m_lengthFIRFFT; i++){
+        m_pFftInput[i] = m_pFftCoefficients[i] = m_pFftReal1[i] = m_pFftImag1[i] = m_pFftReal2[i] = m_pFftImag2[i] = m_pFftFilteredReal[i] = m_pFftFilteredImag[i] = m_pFftOutputReal[i] = m_pFftOutputImag[i] = 0.0;
     }
 }
 
 void
-FIRFilter::process(const float* input, const float* coefficients, float* output)
+FIRFilter::process(const float* pInput, const float* pCoefficients, float* pOutput)
 {
     //Copy to same length FFT buffers
-    for(int i = 0; i < m_lengthFIRFFT; i++){
-        fftInput[i] = i < m_lengthInput ? input[i] : 0.0;
-        fftCoefficients[i] = i < m_numberOfCoefficients ? coefficients[i] : 0.0;
+    for(unsigned int i = 0; i < m_lengthFIRFFT; i++){
+        m_pFftInput[i] = i < m_lengthInput ? pInput[i] : 0.0;
+        m_pFftCoefficients[i] = i < m_numberOfCoefficients ? pCoefficients[i] : 0.0;
     }
     
-    FFT::forward(m_lengthFIRFFT, fftInput, 0, fftReal1, fftImag1);
-    FFT::forward(m_lengthFIRFFT, fftCoefficients, 0, fftReal2, fftImag2);
+    FFT::forward(m_lengthFIRFFT, m_pFftInput, 0, m_pFftReal1, m_pFftImag1);
+    FFT::forward(m_lengthFIRFFT, m_pFftCoefficients, 0, m_pFftReal2, m_pFftImag2);
     
     //Multiply FFT coefficients. Multiplication in freq domain is convolution in time domain.
-    for (int i = 0; i < m_lengthFIRFFT; i++){
-        fftFilteredReal[i] = (fftReal1[i] * fftReal2[i]) - (fftImag1[i] * fftImag2[i]);
-        fftFilteredImag[i] = (fftReal1[i] * fftImag2[i]) + (fftReal2[i] * fftImag1[i]);
+    for (unsigned int i = 0; i < m_lengthFIRFFT; i++){
+        m_pFftFilteredReal[i] = (m_pFftReal1[i] * m_pFftReal2[i]) - (m_pFftImag1[i] * m_pFftImag2[i]);
+        m_pFftFilteredImag[i] = (m_pFftReal1[i] * m_pFftImag2[i]) + (m_pFftReal2[i] * m_pFftImag1[i]);
     }
-    FFT::inverse(m_lengthFIRFFT, fftFilteredReal, fftFilteredImag, fftOutputReal, fftOutputImag);
+    
+    FFT::inverse(m_lengthFIRFFT, m_pFftFilteredReal, m_pFftFilteredImag, m_pFftOutputReal, m_pFftOutputImag);
     
     //copy to output
-    for (int i = 0; i < m_lengthInput; i++){
-        output[i] = fftOutputReal[i];
+    for (unsigned int i = 0; i < m_lengthInput; i++){
+        pOutput[i] = m_pFftOutputReal[i];
     }
 }
 
@@ -85,15 +86,15 @@
 void
 FIRFilter::cleanup()
 {
-    delete []fftInput;
-    delete []fftCoefficients;
-    delete []fftReal1;
-    delete []fftImag1;
-    delete []fftReal2;
-    delete []fftImag2;
-    delete []fftFilteredReal;
-    delete []fftFilteredImag;
-    delete []fftOutputReal;
-    delete []fftOutputImag;
-    fftInput = fftCoefficients = fftReal1 = fftImag1 = fftReal2 = fftImag2 = fftFilteredReal = fftFilteredImag = fftOutputReal = fftOutputImag = 0;
+    delete []m_pFftInput;
+    delete []m_pFftCoefficients;
+    delete []m_pFftReal1;
+    delete []m_pFftImag1;
+    delete []m_pFftReal2;
+    delete []m_pFftImag2;
+    delete []m_pFftFilteredReal;
+    delete []m_pFftFilteredImag;
+    delete []m_pFftOutputReal;
+    delete []m_pFftOutputImag;
+    m_pFftInput = m_pFftCoefficients = m_pFftReal1 = m_pFftImag1 = m_pFftReal2 = m_pFftImag2 = m_pFftFilteredReal = m_pFftFilteredImag = m_pFftOutputReal = m_pFftOutputImag = 0;
 }
--- a/FIRFilter.h	Wed Aug 13 10:47:39 2014 +0100
+++ b/FIRFilter.h	Wed Aug 13 14:18:00 2014 +0100
@@ -15,24 +15,24 @@
 
 class FIRFilter{
 public:
-    FIRFilter(const unsigned int lengthInput, const unsigned int numberOfCoefficients);
+    FIRFilter(const size_t &lengthInput, const size_t &numberOfCoefficients);
     ~FIRFilter();
-    void process(const float *input, const float *coefficients, float *output);
+    void process(const float *pInput, const float *pCoefficients, float * pOutput);
 private:
-    unsigned int m_lengthInput;
-    unsigned int m_numberOfCoefficients;
-    unsigned int m_lengthFIRFFT;
+    size_t m_lengthInput;
+    size_t m_numberOfCoefficients;
+    int m_lengthFIRFFT;
     
-    double *fftInput;
-    double *fftCoefficients;
-    double *fftReal1;
-    double *fftImag1;
-    double *fftReal2;
-    double *fftImag2;
-    double *fftFilteredReal;
-    double *fftFilteredImag;
-    double *fftOutputReal;
-    double *fftOutputImag;
+    double *m_pFftInput;
+    double *m_pFftCoefficients;
+    double *m_pFftReal1;
+    double *m_pFftImag1;
+    double *m_pFftReal2;
+    double *m_pFftImag2;
+    double *m_pFftFilteredReal;
+    double *m_pFftFilteredImag;
+    double *m_pFftOutputReal;
+    double *m_pFftOutputImag;
     
     void initialise();
     void cleanup();
--- a/NoveltyCurve.cpp	Wed Aug 13 10:47:39 2014 +0100
+++ b/NoveltyCurve.cpp	Wed Aug 13 14:18:00 2014 +0100
@@ -12,16 +12,15 @@
 #include <memory>
 using namespace std;
 
-NoveltyCurve::NoveltyCurve(float samplingFrequency, int fftLength, int numberOfBlocks, int compressionConstant) :
+NoveltyCurve::NoveltyCurve(const float &samplingFrequency, const size_t &fftLength, const size_t &numberOfBlocks, const size_t &compressionConstant) :
     m_samplingFrequency(samplingFrequency),
     m_fftLength(fftLength),
     m_blockSize(fftLength/2 + 1),
     m_numberOfBlocks(numberOfBlocks),
     m_compressionConstant(compressionConstant),
     m_numberOfBands(5),
-    m_bandBoundaries(NULL),
-    m_hannLength(65),
-    m_bandSum(NULL)
+    m_pBandBoundaries(0),
+    m_pBandSum(0)
 {
     initialise();
 }
@@ -33,35 +32,35 @@
 //allocate all space and set variable
 void
 NoveltyCurve::initialise(){
-    data = vector<float>(m_numberOfBlocks);
     
-    // for bandwise processing, the band is split into 5 bands. m_bandBoundaries contains the upper and lower bin boundaries for each band.
-    m_bandBoundaries = new int[m_numberOfBands+1];
-    m_bandBoundaries[0] = 0;
-    for (int band = 1; band < m_numberOfBands; band++){
-        float lowFreq = 500*pow(2.5, band-1);
-        m_bandBoundaries[band] = m_fftLength*lowFreq/m_samplingFrequency;
+    // for bandwise processing, the band is split into 5 bands. m_pBandBoundaries contains the upper and lower bin boundaries for each band.
+    m_pBandBoundaries = new int[m_numberOfBands+1];
+    m_pBandBoundaries[0] = 0;
+    for (unsigned int band = 1; band < m_numberOfBands; band++){
+        float lowFreq = 500*pow(2.5, (int)band-1);
+        m_pBandBoundaries[band] = m_fftLength*lowFreq/m_samplingFrequency;
     }
-    m_bandBoundaries[m_numberOfBands] = m_blockSize;
+    m_pBandBoundaries[m_numberOfBands] = m_blockSize;
     
-    m_bandSum = new float [m_numberOfBands];
+    m_pBandSum = new float [m_numberOfBands];
 }
 
 //delete space allocated in initialise()
 void
 NoveltyCurve::cleanup(){
-    delete []m_bandBoundaries;
-    m_bandBoundaries = NULL;
-    delete []m_bandSum;
-    m_bandSum = NULL;
+    delete []m_pBandBoundaries;
+    m_pBandBoundaries = 0;
+    delete []m_pBandSum;
+    m_pBandSum = 0;
 }
 
 //calculate max of spectrogram
-float NoveltyCurve::calculateMax(vector< vector<float> > &spectrogram){
+float NoveltyCurve::calculateMax(const vector< vector<float> > &spectrogram) const
+{
     float max = 0;
     
-    for (int j = 0; j < m_numberOfBlocks; j++){
-        for (int i = 0; i < m_blockSize; i++){
+    for (unsigned int j = 0; j < m_numberOfBlocks; j++){
+        for (unsigned int i = 0; i < m_blockSize; i++){
             max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
         }
     }
@@ -71,48 +70,50 @@
 
 //subtract local average of novelty curve
 //uses m_hannWindow as filter
-void NoveltyCurve::subtractLocalAverage(vector<float> &noveltyCurve){
+void NoveltyCurve::subtractLocalAverage(vector<float> &noveltyCurve, const size_t &smoothLength) const
+{
     vector<float> localAverage(m_numberOfBlocks);
     
-    float * m_hannWindow = new float[m_hannLength];
-    WindowFunction::hanning(m_hannWindow, m_hannLength, true);
+    float * m_hannWindow = new float[smoothLength];
+    WindowFunction::hanning(m_hannWindow, smoothLength, true);
     
-    FIRFilter filter(m_numberOfBlocks, m_hannLength);
+    FIRFilter filter(m_numberOfBlocks, smoothLength);
     filter.process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
     
     assert(noveltyCurve.size() == m_numberOfBlocks);
-    for (int i = 0; i < m_numberOfBlocks; i++){
+    for (unsigned int i = 0; i < m_numberOfBlocks; i++){
         noveltyCurve[i] -= localAverage[i];
         noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
     }
     
     delete []m_hannWindow;
-    m_hannWindow = NULL;
+    m_hannWindow = 0;
 }
 
 //smoothed differentiator filter. Flips upper half of hanning window about y-axis to create coefficients.
-void NoveltyCurve::smoothedDifferentiator(vector< vector<float> > &spectrogram, int smoothLength){
+void NoveltyCurve::smoothedDifferentiator(vector< vector<float> > &spectrogram, const size_t &smoothLength) const
+{
     
     float * diffHannWindow = new float [smoothLength];
     WindowFunction::hanning(diffHannWindow, smoothLength, true);
     
     if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0;
-    for(int i = (smoothLength+1)/2; i < smoothLength; i++){
+    for(unsigned int i = (smoothLength+1)/2; i < smoothLength; i++){
         diffHannWindow[i] = -diffHannWindow[i];
     }
     
     FIRFilter smoothFilter(m_numberOfBlocks, smoothLength);
     
-    for (int i = 0; i < m_blockSize; i++){
+    for (unsigned int i = 0; i < m_blockSize; i++){
         smoothFilter.process(&spectrogram[i][0], diffHannWindow, &spectrogram[i][0]);
     }
 }
 
 //half rectification (set negative to zero)
-void NoveltyCurve::halfWaveRectify(vector< vector<float> > &spectrogram){
-    
-    for (int block = 0; block < m_numberOfBlocks; block++){
-        for (int k = 0; k < m_blockSize; k++){
+void NoveltyCurve::halfWaveRectify(vector< vector<float> > &spectrogram) const
+{
+    for (unsigned int block = 0; block < m_numberOfBlocks; block++){
+        for (unsigned int k = 0; k < m_blockSize; k++){
             if (spectrogram[k][block] < 0.0) spectrogram[k][block] = 0.0;
         }
     }
@@ -120,15 +121,17 @@
 
 //process method
 vector<float>
-NoveltyCurve::spectrogramToNoveltyCurve(vector< vector<float> > spectrogram){
+NoveltyCurve::spectrogramToNoveltyCurve(Spectrogram spectrogram) const
+{
+    std::vector<float> noveltyCurve(m_numberOfBlocks);
     
     assert(spectrogram.size() == m_blockSize);
     assert(spectrogram[0].size() == m_numberOfBlocks);
     
     //normalise and log spectrogram
     float normaliseScale = calculateMax(spectrogram);
-    for (int block = 0; block < m_numberOfBlocks; block++){
-        for (int k = 0; k < m_blockSize; k++){
+    for (unsigned int block = 0; block < m_numberOfBlocks; block++){
+        for (unsigned int k = 0; k < m_blockSize; k++){
             if(normaliseScale != 0.0) spectrogram[k][block] /= normaliseScale; //normalise
             spectrogram[k][block] = log(1+m_compressionConstant*spectrogram[k][block]);
         }
@@ -140,26 +143,26 @@
     halfWaveRectify(spectrogram);
     
     //bandwise processing
-    for (int block = 0; block < m_numberOfBlocks; block++){
-        for (int band = 0; band < m_numberOfBands; band++){
-            int k = m_bandBoundaries[band];
-            int bandEnd = m_bandBoundaries[band+1];
-            m_bandSum[band] = 0;
+    for (unsigned int block = 0; block < m_numberOfBlocks; block++){
+        for (unsigned int band = 0; band < m_numberOfBands; band++){
+            int k = m_pBandBoundaries[band];
+            int bandEnd = m_pBandBoundaries[band+1];
+            m_pBandSum[band] = 0;
             
             while(k < bandEnd){
-                m_bandSum[band] += spectrogram[k][block];
+                m_pBandSum[band] += spectrogram[k][block];
                 k++;
             }
         }
         float total = 0;
-        for(int band = 0; band < m_numberOfBands; band++){
-            total += m_bandSum[band];
+        for(unsigned int band = 0; band < m_numberOfBands; band++){
+            total += m_pBandSum[band];
         }
-        data[block] = total/m_numberOfBands;
+        noveltyCurve[block] = total/m_numberOfBands;
     }
     
     //subtract local averages
-    subtractLocalAverage(data);
+    subtractLocalAverage(noveltyCurve, 65);
     
-    return data;
+    return noveltyCurve;
 }
--- a/NoveltyCurve.h	Wed Aug 13 10:47:39 2014 +0100
+++ b/NoveltyCurve.h	Wed Aug 13 14:18:00 2014 +0100
@@ -18,6 +18,7 @@
 #include "FIRFilter.h"
 #include "WindowFunction.h"
 #include <cassert>
+#include "Spectrogram.h"
 
 class NoveltyCurve{
     float m_samplingFrequency;
@@ -26,23 +27,21 @@
     int m_numberOfBlocks;
     int m_compressionConstant;
     int m_numberOfBands;
-    int * m_bandBoundaries;
-    int m_hannLength;
-    float * m_bandSum;
-    std::vector<float> data;
+    int * m_pBandBoundaries;
+    float * m_pBandSum;
     
     void initialise();
     void cleanup();
-    float calculateMax(std::vector< std::vector<float> > &spectrogram);
-    void subtractLocalAverage(std::vector<float> &noveltyCurve);
-    void smoothedDifferentiator(std::vector< std::vector<float> > &spectrogram, int smoothLength);
-    void halfWaveRectify(std::vector< std::vector<float> > &spectrogram);
+    float calculateMax(const std::vector< std::vector<float> > &spectrogram) const;
+    void subtractLocalAverage(std::vector<float> &noveltyCurve, const size_t &smoothLength) const;
+    void smoothedDifferentiator(std::vector< std::vector<float> > &spectrogram, const size_t &smoothLength) const;
+    void halfWaveRectify(std::vector< std::vector<float> > &spectrogram) const;
     
 public:
     
-    NoveltyCurve(float samplingFrequency, int fftLength, int numberOfBlocks, int compressionConstant);
+    NoveltyCurve(const float &samplingFrequency, const size_t &fftLength, const size_t &numberOfBlocks, const size_t &compressionConstant);
     ~NoveltyCurve();
-    std::vector<float> spectrogramToNoveltyCurve(std::vector< std::vector<float> > spectrogram);
+    std::vector<float> spectrogramToNoveltyCurve(Spectrogram spectrogram) const;
 };
 
 #endif /* defined(__Tempogram__NoveltyCurve__) */
--- a/Spectrogram.cpp	Wed Aug 13 10:47:39 2014 +0100
+++ b/Spectrogram.cpp	Wed Aug 13 14:18:00 2014 +0100
@@ -9,16 +9,17 @@
 #include "Spectrogram.h"
 using namespace std;
 using Vamp::FFT;
+#include <iostream>
 
-SpectrogramProcessor::SpectrogramProcessor(unsigned int inputLength, unsigned int windowLength, unsigned int fftLength, unsigned int hopSize) :
+SpectrogramProcessor::SpectrogramProcessor(const size_t &inputLength, const size_t &windowLength, const size_t &fftLength, const size_t &hopSize) :
     m_inputLength(inputLength),
     m_windowLength(windowLength),
     m_fftLength(fftLength),
     m_hopSize(hopSize),
     m_numberOfOutputBins(ceil(fftLength/2) + 1),
-    fftInput(0),
-    fftOutputReal(0),
-    fftOutputImag(0)
+    m_pFftInput(0),
+    m_pFftOutputReal(0),
+    m_pFftOutputImag(0)
 {
     initialise();
 }
@@ -28,54 +29,55 @@
 }
 
 void SpectrogramProcessor::initialise(){
-    fftInput = new double [m_fftLength];
-    fftOutputReal = new double [m_fftLength];
-    fftOutputImag = new double [m_fftLength];
-    
-    int numberOfBlocks = ceil(m_inputLength/m_hopSize) + 2*(ceil(m_windowLength/m_hopSize)-1); //The last term corresponds to overlaps at the beginning and end with padded zeros. I.e., if m_hopSize = m_windowLength/2, there'll be 1 overlap at each end. If m_hopSize = m_windowLength/4, there'll be 3 overlaps at each end, etc...
-    spectrogramOutput = vector< vector<float> >(m_numberOfOutputBins, vector<float>(numberOfBlocks));
+    m_pFftInput = new double [m_fftLength];
+    m_pFftOutputReal = new double [m_fftLength];
+    m_pFftOutputImag = new double [m_fftLength];
 }
 
 void SpectrogramProcessor::cleanup(){
-    delete []fftInput;
-    delete []fftOutputReal;
-    delete []fftOutputImag;
+    delete []m_pFftInput;
+    delete []m_pFftOutputReal;
+    delete []m_pFftOutputImag;
     
-    fftInput = fftOutputReal = fftOutputImag = 0;
+    m_pFftInput = m_pFftOutputReal = m_pFftOutputImag = 0;
 }
 
 //process method
-vector< vector<float> > SpectrogramProcessor::process(const float * const input, const float * window){
+Spectrogram SpectrogramProcessor::process(const float * const pInput, const float * pWindow) const
+{
+    int numberOfBlocks = ceil(m_inputLength/m_hopSize) + 2*(ceil(m_windowLength/m_hopSize)-1); //The last term corresponds to overlaps at the beginning and end with padded zeros. I.e., if m_hopSize = m_windowLength/2, there'll be 1 overlap at each end. If m_hopSize = m_windowLength/4, there'll be 3 overlaps at each end, etc...
+    Spectrogram spectrogram(m_numberOfOutputBins, vector<float>(numberOfBlocks));
     
     int readPointerBeginIndex = m_hopSize-m_windowLength;
-    int writeBlockPointer = 0;
+    unsigned int writeBlockPointer = 0;
     
-    while(readPointerBeginIndex < m_inputLength){
+    while(readPointerBeginIndex < (int)m_inputLength){
         
         int readPointer = readPointerBeginIndex;
-        for (int n = 0; n < m_windowLength; n++){
-            if(readPointer < 0 || readPointer >= m_inputLength){
-                fftInput[n] = 0.0; //pad with zeros
+        for (unsigned int n = 0; n < m_windowLength; n++){
+            if(readPointer < 0 || readPointer >= (int)m_inputLength){
+                m_pFftInput[n] = 0.0; //pad with zeros
             }
             else{
-                fftInput[n] = input[readPointer] * window[n];
+                m_pFftInput[n] = pInput[readPointer] * pWindow[n];
             }
             readPointer++;
         }
-        for (int n = m_windowLength; n < m_fftLength; n++){
-            fftInput[n] = 0.0;
+        for (unsigned int n = m_windowLength; n < m_fftLength; n++){
+            m_pFftInput[n] = 0.0;
         }
         
-        FFT::forward(m_fftLength, fftInput, 0, fftOutputReal, fftOutputImag);
+        FFT::forward(m_fftLength, m_pFftInput, 0, m_pFftOutputReal, m_pFftOutputImag);
         
         //@todo: sample at logarithmic spacing? Leave for host?
-        for(int k = 0; k < m_numberOfOutputBins; k++){
-            spectrogramOutput[k][writeBlockPointer] = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power?
+        for(unsigned int k = 0; k < m_numberOfOutputBins; k++){
+            spectrogram[k][writeBlockPointer] = (m_pFftOutputReal[k]*m_pFftOutputReal[k] + m_pFftOutputImag[k]*m_pFftOutputImag[k]); //Magnitude or power?
+            //std::cout << spectrogram[k][writeBlockPointer] << std::endl;
         }
         
         readPointerBeginIndex += m_hopSize;
         writeBlockPointer++;
     }
     
-    return spectrogramOutput;
+    return spectrogram;
 }
--- a/Spectrogram.h	Wed Aug 13 10:47:39 2014 +0100
+++ b/Spectrogram.h	Wed Aug 13 14:18:00 2014 +0100
@@ -12,23 +12,26 @@
 #include <vamp-sdk/FFT.h>
 #include <cmath>
 
+typedef std::vector <std::vector<float> > Spectrogram;
+typedef std::vector <std::vector<float> > SpectrogramTransposed;
+
 class SpectrogramProcessor{
-    int m_inputLength;
-    int m_windowLength;
-    int m_fftLength;
-    int m_hopSize;
-    int m_numberOfOutputBins;
-    double * fftInput;
-    double * fftOutputReal;
-    double * fftOutputImag;
-    std::vector< std::vector <float> > spectrogramOutput;
+    size_t m_inputLength;
+    size_t m_windowLength;
+    size_t m_fftLength;
+    size_t m_hopSize;
+    size_t m_numberOfOutputBins;
+    double * m_pFftInput;
+    double * m_pFftOutputReal;
+    double * m_pFftOutputImag;
     
     void initialise();
     void cleanup();
 public:
-    std::vector< std::vector<float> > process(const float * const input, const float * window);
-    SpectrogramProcessor(unsigned int inputLength, unsigned int windowLength, unsigned int fftLength, unsigned int hopSize);
+    SpectrogramProcessor(const size_t &inputLength, const size_t &windowLength, const size_t &fftLength, const size_t &hopSize);
     ~SpectrogramProcessor();
+    
+    std::vector< std::vector<float> > process(const float * const pInput, const float * pWindow) const;
 };
 
 #endif /* defined(__Tempogram__Spectrogram__) */
--- a/Tempogram.cpp	Wed Aug 13 10:47:39 2014 +0100
+++ b/Tempogram.cpp	Wed Aug 13 14:18:00 2014 +0100
@@ -16,16 +16,17 @@
     Plugin(inputSampleRate),
     m_blockSize(0),
     m_stepSize(0),
-    compressionConstant(1000), //parameter
-    minDB(0),
-    windowLength(128), //parameter
-    fftLength(4096), //parameter
-    thopSize(64), //parameter
-    minBPM(30),
-    maxBPM(480),
-    minBin(0), //set in initialise()
-    maxBin(0), //set in initialise()
-    numberOfBlocks(0) //incremented in process()
+    m_compressionConstant(1000), //parameter
+    m_minDB(0),
+    m_log2WindowLength(10),
+    m_windowLength(pow((float)2,(float)m_log2WindowLength)), //parameter
+    m_fftLength(4096), //parameter
+    m_hopSize(64), //parameter
+    m_minBPM(30),
+    m_maxBPM(480),
+    m_minBin(0), //set in initialise()
+    m_maxBin(0), //set in initialise()
+    m_numberOfBlocks(0) //incremented in process()
 
     // Also be sure to set your plugin parameters (presumably stored
     // in member variables) to their default values here -- the host
@@ -142,15 +143,18 @@
     d.isQuantized = false;
     list.push_back(d);
 
-    d.identifier = "TN";
+    d.identifier = "log2TN";
     d.name = "Tempogram Window Length";
     d.description = "FFT window length when analysing the novelty curve and extracting the tempogram time-frequency function.";
     d.unit = "";
-    d.minValue = 1024;
-    d.maxValue = 4096;
-    d.defaultValue = 128;
+    d.minValue = 7;
+    d.maxValue = 12;
+    d.defaultValue = 10;
     d.isQuantized = true;
-    d.quantizeStep = 128;
+    d.quantizeStep = 1;
+    for (int i = d.minValue; i <= d.maxValue; i++){
+        d.valueNames.push_back(floatToString(pow((float)2,(float)i)));
+    }
     list.push_back(d);
     
     d.identifier = "minBPM";
@@ -182,16 +186,16 @@
 Tempogram::getParameter(string identifier) const
 {
     if (identifier == "C") {
-        return compressionConstant; // return the ACTUAL current value of your parameter here!
+        return m_compressionConstant; // return the ACTUAL current value of your parameter here!
     }
-    if (identifier == "TN"){
-        return windowLength;
+    if (identifier == "log2TN"){
+        return m_log2WindowLength;
     }
     if (identifier == "minBPM") {
-        return minBPM;
+        return m_minBPM;
     }
     if (identifier == "maxBPM"){
-        return maxBPM;
+        return m_maxBPM;
     }
     
     return 0;
@@ -202,16 +206,17 @@
 {
     
     if (identifier == "C") {
-        compressionConstant = value; // set the actual value of your parameter
+        m_compressionConstant = value; // set the actual value of your parameter
     }
-    if (identifier == "TN") {
-        windowLength = value;
+    if (identifier == "log2TN") {
+        m_windowLength = pow(2,value);
+        m_log2WindowLength = value;
     }
     if (identifier == "minBPM") {
-        minBPM = value;
+        m_minBPM = value;
     }
     if (identifier == "maxBPM"){
-        maxBPM = value;
+        m_maxBPM = value;
     }
     
 }
@@ -267,14 +272,14 @@
     d.description = "Tempogram";
     d.unit = "BPM";
     d.hasFixedBinCount = true;
-    d.binCount = maxBin - minBin + 1;
+    d.binCount = m_maxBin - m_minBin + 1;
     d.hasKnownExtents = false;
     d.isQuantized = false;
     d.sampleType = OutputDescriptor::FixedSampleRate;
-    d_sampleRate = tempogramInputSampleRate/thopSize;
+    d_sampleRate = tempogramInputSampleRate/m_hopSize;
     d.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0;
-    for(int i = minBin; i <= maxBin; i++){
-        float w = ((float)i/fftLength)*(tempogramInputSampleRate);
+    for(int i = m_minBin; i <= (int)m_maxBin; i++){
+        float w = ((float)i/m_fftLength)*(tempogramInputSampleRate);
         d.binNames.push_back(floatToString(w*60));
     }
     d.hasDuration = false;
@@ -306,17 +311,17 @@
     // Real initialisation work goes here!
     m_blockSize = blockSize;
     m_stepSize = stepSize;
-    minDB = pow(10,(float)-74/20);
+    m_minDB = pow(10,(float)-74/20);
     
-    if (minBPM > maxBPM){
-        minBPM = 30;
-        maxBPM = 480;
+    if (m_minBPM > m_maxBPM){
+        m_minBPM = 30;
+        m_maxBPM = 480;
     }
     float tempogramInputSampleRate = (float)m_inputSampleRate/m_stepSize;
-    minBin = (unsigned int)(max(floor(((minBPM/60)/tempogramInputSampleRate)*fftLength), (float)0.0));
-    maxBin = (unsigned int)(min(ceil(((maxBPM/60)/tempogramInputSampleRate)*fftLength), (float)fftLength/2));
+    m_minBin = (unsigned int)(max(floor(((m_minBPM/60)/tempogramInputSampleRate)*m_fftLength), (float)0.0));
+    m_maxBin = (unsigned int)(min(ceil(((m_maxBPM/60)/tempogramInputSampleRate)*m_fftLength), (float)m_fftLength/2));
     
-    specData = vector< vector<float> >(m_blockSize/2 + 1);
+    m_spectrogram = vector< vector<float> >(m_blockSize/2 + 1);
     
     return true;
 }
@@ -330,8 +335,8 @@
 {
     // Clear buffers, reset stored values, etc
     ncTimestamps.clear();
-    specData.clear();
-    specData = vector< vector<float> >(m_blockSize/2 + 1);
+    m_spectrogram.clear();
+    m_spectrogram = vector< vector<float> >(m_blockSize/2 + 1);
 }
 
 Tempogram::FeatureSet
@@ -345,13 +350,13 @@
     const float *in = inputBuffers[0];
 
     //calculate magnitude of FrequencyDomain input
-    for (int i = 0; i < n; i++){
+    for (unsigned int i = 0; i < n; i++){
         float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]);
-        magnitude = magnitude > minDB ? magnitude : minDB;
-        specData[i].push_back(magnitude);
+        magnitude = magnitude > m_minDB ? magnitude : m_minDB;
+        m_spectrogram[i].push_back(magnitude);
     }
     
-    numberOfBlocks++;
+    m_numberOfBlocks++;
     ncTimestamps.push_back(timestamp); //save timestamp
 
     return featureSet;
@@ -361,35 +366,35 @@
 Tempogram::getRemainingFeatures()
 {
     
-    float * hannWindowtN = new float[windowLength];
-    for (int i = 0; i < windowLength; i++){
+    float * hannWindowtN = new float[m_windowLength];
+    for (unsigned int i = 0; i < m_windowLength; i++){
         hannWindowtN[i] = 0.0;
     }
     
     FeatureSet featureSet;
     
-    //initialise noveltycurve processor
-    NoveltyCurve nc(m_inputSampleRate, m_blockSize, numberOfBlocks, compressionConstant);
-    noveltyCurve = nc.spectrogramToNoveltyCurve(specData); //calculate novelty curve from magnitude data
+    //initialise m_noveltyCurve processor
+    NoveltyCurve nc(m_inputSampleRate, m_blockSize, m_numberOfBlocks, m_compressionConstant);
+    m_noveltyCurve = nc.spectrogramToNoveltyCurve(m_spectrogram); //calculate novelty curve from magnitude data
     
     //push novelty curve data to featureset 1 and set timestamps
-    for (int i = 0; i < numberOfBlocks; i++){
+    for (unsigned int i = 0; i < m_numberOfBlocks; i++){
         Feature feature;
-        feature.values.push_back(noveltyCurve[i]);
+        feature.values.push_back(m_noveltyCurve[i]);
         feature.hasTimestamp = true;
         feature.timestamp = ncTimestamps[i];
         featureSet[1].push_back(feature);
     }
     
     //window function for spectrogram
-    WindowFunction::hanning(hannWindowtN,windowLength);
+    WindowFunction::hanning(hannWindowtN,m_windowLength);
     
     //initialise spectrogram processor
-    SpectrogramProcessor spectrogramProcessor(numberOfBlocks, windowLength, fftLength, thopSize);
+    SpectrogramProcessor spectrogramProcessor(m_numberOfBlocks, m_windowLength, m_fftLength, m_hopSize);
     //compute spectrogram from novelty curve data (i.e., tempogram)
-    vector< vector<float> > tempogram = spectrogramProcessor.process(&noveltyCurve[0], hannWindowtN);
+    Spectrogram tempogram = spectrogramProcessor.process(&m_noveltyCurve[0], hannWindowtN);
     
-    int timePointer = thopSize-windowLength/2;
+    int timePointer = m_hopSize-m_windowLength/2;
     int tempogramLength = tempogram[0].size();
     
     //push tempogram data to featureset 0 and set timestamps.
@@ -398,21 +403,22 @@
         
         int timeMS = floor(1000*(m_stepSize*timePointer)/m_inputSampleRate + 0.5);
         
-        assert(tempogram.size() == (fftLength/2 + 1));
-        for(int k = minBin; k < maxBin; k++){
+        assert(tempogram.size() == (m_fftLength/2 + 1));
+        for(int k = m_minBin; k < (int)m_maxBin; k++){
             feature.values.push_back(tempogram[k][block]);
+            //cout << tempogram[k][block] << endl;
         }
         feature.hasTimestamp = true;
         feature.timestamp = RealTime::fromMilliseconds(timeMS);
         featureSet[0].push_back(feature);
         
-        timePointer += thopSize;
+        timePointer += m_hopSize;
     }
     
     //float func = [](){ cout << "Hello"; };
     
     delete []hannWindowtN;
-    hannWindowtN = NULL;
+    hannWindowtN = 0;
     
     return featureSet;
 }
--- a/Tempogram.h	Wed Aug 13 10:47:39 2014 +0100
+++ b/Tempogram.h	Wed Aug 13 14:18:00 2014 +0100
@@ -75,28 +75,27 @@
     // plugin-specific data and methods go here
     size_t m_blockSize;
     size_t m_stepSize;
-    float compressionConstant;
-    float *previousY;
-    float *currentY;
-    vector< vector<float> > specData; //spectrogram data
-    vector<float> noveltyCurve; //novelty curve data
-    float minDB;
+    float m_compressionConstant;
+    vector< vector<float> > m_spectrogram; //spectrogram data
+    vector<float> m_noveltyCurve; //novelty curve data
+    float m_minDB;
     
     void cleanup(); //used to release anything allocated in initialise()
     string floatToString(float value) const;
     void updateBPMParameters();
     
     //FFT params for noveltyCurve -> tempogra
-    unsigned int windowLength;
-    unsigned int fftLength;
-    unsigned int thopSize;
+    int m_log2WindowLength;
+    size_t m_windowLength;
+    size_t m_fftLength;
+    size_t m_hopSize;
     
-    float minBPM; // tempogram output bin range min
-    float maxBPM; // tempogram output bin range max
-    unsigned int minBin;
-    unsigned int maxBin;
+    float m_minBPM; // tempogram output bin range min
+    float m_maxBPM; // tempogram output bin range max
+    unsigned int m_minBin;
+    unsigned int m_maxBin;
     
-    int numberOfBlocks;
+    unsigned int m_numberOfBlocks;
     
     vector<Vamp::RealTime> ncTimestamps;
 };
--- a/WindowFunction.cpp	Wed Aug 13 10:47:39 2014 +0100
+++ b/WindowFunction.cpp	Wed Aug 13 14:18:00 2014 +0100
@@ -11,10 +11,10 @@
 
 //static function
 void
-WindowFunction::hanning(float *window, const unsigned int N, const bool normalise){
+WindowFunction::hanning(float * window, const unsigned int &N, const bool &normalise){
     
     float sum = 0;
-    for(int i = 0; i < N; i++){
+    for(unsigned int i = 0; i < N; i++){
         window[i] = 0.5*(1-cos((float)2*M_PI*i/N));
         sum += window[i];
     }
--- a/WindowFunction.h	Wed Aug 13 10:47:39 2014 +0100
+++ b/WindowFunction.h	Wed Aug 13 14:18:00 2014 +0100
@@ -15,7 +15,7 @@
 
 class WindowFunction{
 public:
-    static void hanning(float *signal, const unsigned int N, const bool normalise = false);
+    static void hanning(float *signal, const unsigned int &N, const bool &normalise = false);
 };
 
 #endif /* defined(__Tempogram__WindowFunction__) */