annotate NoveltyCurve.cpp @ 5:8d7e336b41e9

Adding NoveltyCurve.*
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Tue, 05 Aug 2014 15:59:15 +0100
parents
children 21147df9cb2d
rev   line source
c@5 1 //
c@5 2 // NoveltyCurve.cpp
c@5 3 // Tempogram
c@5 4 //
c@5 5 // Created by Carl Bussey on 10/07/2014.
c@5 6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
c@5 7 //
c@5 8
c@5 9 #include <cmath>
c@5 10 #include <vector>
c@5 11 #include <iostream>
c@5 12 #include "FIRFilter.h"
c@5 13 #include "WindowFunction.h"
c@5 14 using namespace std;
c@5 15 #include "NoveltyCurve.h"
c@5 16
c@5 17 NoveltyCurve::NoveltyCurve(float samplingFrequency, int blockSize, int numberOfBlocks, int compressionConstant) :
c@5 18 m_samplingFrequency(samplingFrequency),
c@5 19 m_blockSize(blockSize),
c@5 20 m_numberOfBlocks(numberOfBlocks),
c@5 21 m_compressionConstant(compressionConstant),
c@5 22 m_numberOfBands(5),
c@5 23 m_bandBoundaries(NULL),
c@5 24 m_hannLength(65),
c@5 25 m_hannWindow(NULL),
c@5 26 m_bandSum(NULL)
c@5 27 {
c@5 28 initialise();
c@5 29 }
c@5 30
c@5 31 NoveltyCurve::~NoveltyCurve(){
c@5 32 cleanup();
c@5 33 }
c@5 34
c@5 35 void
c@5 36 NoveltyCurve::initialise(){
c@5 37 data = vector<float>(m_numberOfBlocks);
c@5 38
c@5 39 m_hannWindow = new float[m_hannLength];
c@5 40 WindowFunction::hanning(m_hannWindow, m_hannLength, true);
c@5 41
c@5 42 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable
c@5 43
c@5 44 m_bandBoundaries[0] = 0;
c@5 45 for (int band = 1; band < m_numberOfBands; band++){
c@5 46 float lowFreq = 500*pow(2.5, band-1);
c@5 47 m_bandBoundaries[band] = m_blockSize*lowFreq/m_samplingFrequency;
c@5 48 }
c@5 49 m_bandBoundaries[m_numberOfBands] = m_blockSize/2 + 1;
c@5 50
c@5 51 m_bandSum = new float * [m_numberOfBands];
c@5 52 for (int i = 0; i < m_numberOfBands; i++){
c@5 53 m_bandSum[i] = new float[m_numberOfBlocks];
c@5 54 }
c@5 55 }
c@5 56
c@5 57 void
c@5 58 NoveltyCurve::cleanup(){
c@5 59 delete []m_hannWindow;
c@5 60 m_hannWindow = NULL;
c@5 61 delete []m_bandBoundaries;
c@5 62 m_bandBoundaries = NULL;
c@5 63
c@5 64 for(int i = 0; i < m_numberOfBands; i++){
c@5 65 delete []m_bandSum[i];
c@5 66 m_bandSum[i] = NULL;
c@5 67 }
c@5 68 delete []m_bandSum;
c@5 69 m_bandSum = NULL;
c@5 70 }
c@5 71
c@5 72 float NoveltyCurve::calculateMax(float ** spectrogram){
c@5 73 int specLength = (m_blockSize/2 + 1);
c@5 74 float max = 0;
c@5 75
c@5 76 for (int j = 0; j < m_numberOfBlocks; j++){
c@5 77 for (int i = 0; i < specLength; i++){
c@5 78 max = max > spectrogram[i][j] ? max : spectrogram[i][j];
c@5 79 }
c@5 80 }
c@5 81
c@5 82 return max;
c@5 83 }
c@5 84
c@5 85 void NoveltyCurve::subtractLocalAverage(float * noveltyCurve){
c@5 86 vector<float> localAverage(m_numberOfBlocks);
c@5 87
c@5 88 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength);
c@5 89 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
c@5 90 delete filter;
c@5 91
c@5 92 for (int i = 0; i < m_numberOfBlocks; i++){
c@5 93 noveltyCurve[i] -= localAverage[i];
c@5 94 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
c@5 95 }
c@5 96 }
c@5 97
c@5 98 vector<float>
c@5 99 NoveltyCurve::spectrogramToNoveltyCurve(float ** spectrogram){
c@5 100
c@5 101 float normaliseScale = calculateMax(spectrogram);
c@5 102
c@5 103 for (int block = 0; block < m_numberOfBlocks; block++){
c@5 104
c@5 105 for (int band = 0; band < m_numberOfBands; band++){
c@5 106
c@5 107 int specIndex = m_bandBoundaries[band];
c@5 108 int bandEnd = m_bandBoundaries[band+1];
c@5 109
c@5 110 while(specIndex < bandEnd){
c@5 111
c@5 112 spectrogram[specIndex][block] /= normaliseScale; //normalise
c@5 113 spectrogram[specIndex][block] = log(1+m_compressionConstant*spectrogram[specIndex][block]);
c@5 114
c@5 115 int currentY = spectrogram[specIndex][block];
c@5 116 int prevBlock = block-1;
c@5 117 int previousY = prevBlock >= 0 ? spectrogram[specIndex][prevBlock] : 0;
c@5 118
c@5 119 if(currentY > previousY){
c@5 120 m_bandSum[band][block] += (currentY - previousY);
c@5 121 }
c@5 122
c@5 123 //cout << specIndex << endl;
c@5 124 specIndex++;
c@5 125 }
c@5 126 }
c@5 127
c@5 128 float total = 0;
c@5 129 for(int band = 0; band < m_numberOfBands; band++){
c@5 130 total += m_bandSum[band][block];
c@5 131 }
c@5 132 float average = total/m_numberOfBands;
c@5 133 data[block] = average;
c@5 134 }
c@5 135
c@5 136 subtractLocalAverage(&data[0]);
c@5 137
c@5 138 return data;
c@5 139 }