annotate NoveltyCurve.cpp @ 7:21147df9cb2d

* Error when deleting Spectrogram object in Tempogram::getRemainingFeatures(). * Moved Spectrogram computation into own class.
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Thu, 07 Aug 2014 16:21:21 +0100
parents 8d7e336b41e9
children be59b4a73f49
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@7 9 #include "NoveltyCurve.h"
c@5 10 using namespace std;
c@5 11
c@7 12 NoveltyCurve::NoveltyCurve(float samplingFrequency, int fftLength, int numberOfBlocks, int compressionConstant) :
c@5 13 m_samplingFrequency(samplingFrequency),
c@7 14 m_fftLength(fftLength),
c@7 15 m_blockSize(fftLength/2 + 1),
c@5 16 m_numberOfBlocks(numberOfBlocks),
c@5 17 m_compressionConstant(compressionConstant),
c@5 18 m_numberOfBands(5),
c@5 19 m_bandBoundaries(NULL),
c@5 20 m_hannLength(65),
c@5 21 m_hannWindow(NULL),
c@5 22 m_bandSum(NULL)
c@5 23 {
c@5 24 initialise();
c@5 25 }
c@5 26
c@5 27 NoveltyCurve::~NoveltyCurve(){
c@5 28 cleanup();
c@5 29 }
c@5 30
c@5 31 void
c@5 32 NoveltyCurve::initialise(){
c@5 33 data = vector<float>(m_numberOfBlocks);
c@5 34
c@5 35 m_hannWindow = new float[m_hannLength];
c@5 36 WindowFunction::hanning(m_hannWindow, m_hannLength, true);
c@5 37
c@5 38 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable
c@5 39
c@5 40 m_bandBoundaries[0] = 0;
c@5 41 for (int band = 1; band < m_numberOfBands; band++){
c@5 42 float lowFreq = 500*pow(2.5, band-1);
c@7 43 m_bandBoundaries[band] = m_fftLength*lowFreq/m_samplingFrequency;
c@5 44 }
c@7 45 m_bandBoundaries[m_numberOfBands] = m_blockSize;
c@5 46
c@7 47 m_bandSum = new float [m_numberOfBands];
c@5 48 }
c@5 49
c@5 50 void
c@5 51 NoveltyCurve::cleanup(){
c@5 52 delete []m_hannWindow;
c@5 53 m_hannWindow = NULL;
c@5 54 delete []m_bandBoundaries;
c@5 55 m_bandBoundaries = NULL;
c@5 56 delete []m_bandSum;
c@5 57 m_bandSum = NULL;
c@5 58 }
c@5 59
c@7 60 float NoveltyCurve::calculateMax(vector< vector<float> > &spectrogram){
c@5 61 float max = 0;
c@5 62
c@5 63 for (int j = 0; j < m_numberOfBlocks; j++){
c@7 64 for (int i = 0; i < m_blockSize; i++){
c@7 65 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
c@5 66 }
c@5 67 }
c@5 68
c@5 69 return max;
c@5 70 }
c@5 71
c@7 72 void NoveltyCurve::subtractLocalAverage(vector<float> &noveltyCurve){
c@5 73 vector<float> localAverage(m_numberOfBlocks);
c@5 74
c@5 75 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength);
c@5 76 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
c@5 77 delete filter;
c@7 78 filter = NULL;
c@5 79
c@7 80 assert(noveltyCurve.size() == m_numberOfBlocks);
c@5 81 for (int i = 0; i < m_numberOfBlocks; i++){
c@5 82 noveltyCurve[i] -= localAverage[i];
c@5 83 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
c@5 84 }
c@5 85 }
c@5 86
c@7 87 void NoveltyCurve::smoothedDifferentiator(vector< vector<float> > &spectrogram, int smoothLength){
c@7 88
c@7 89 //need to make new hannWindow!!
c@7 90 float * diffHannWindow = new float [smoothLength];
c@7 91 WindowFunction::hanning(diffHannWindow, smoothLength, true);
c@7 92
c@7 93 if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0;
c@7 94 for(int i = (smoothLength+1)/2; i < smoothLength; i++){
c@7 95 diffHannWindow[i] = -diffHannWindow[i];
c@7 96 }
c@7 97
c@7 98 FIRFilter *smoothFilter = new FIRFilter(m_numberOfBlocks, smoothLength);
c@7 99
c@7 100 for (int i = 0; i < m_blockSize; i++){
c@7 101 smoothFilter->process(&spectrogram[i][0], diffHannWindow, &spectrogram[i][0]);
c@7 102 }
c@7 103
c@7 104 delete smoothFilter;
c@7 105 smoothFilter = NULL;
c@7 106 }
c@7 107
c@7 108 void NoveltyCurve::halfWaveRectify(vector< vector<float> > &spectrogram){ //should this return spectrogram??
c@7 109
c@7 110 for (int block = 0; block < m_numberOfBlocks; block++){
c@7 111 for (int k = 0; k < m_blockSize; k++){
c@7 112 if (spectrogram[k][block] < 0.0) spectrogram[k][block] = 0.0;
c@7 113 }
c@7 114 }
c@7 115 }
c@7 116
c@5 117 vector<float>
c@7 118 NoveltyCurve::spectrogramToNoveltyCurve(vector< vector<float> > &spectrogram){
c@7 119
c@7 120 assert(spectrogram.size() == m_blockSize);
c@7 121 assert(spectrogram[0].size() == m_numberOfBlocks);
c@5 122
c@5 123 float normaliseScale = calculateMax(spectrogram);
c@5 124
c@5 125 for (int block = 0; block < m_numberOfBlocks; block++){
c@7 126 for (int k = 0; k < m_blockSize; k++){
c@7 127 if(normaliseScale != 0.0) spectrogram[k][block] /= normaliseScale; //normalise
c@7 128 spectrogram[k][block] = log(1+m_compressionConstant*spectrogram[k][block]);
c@7 129 }
c@7 130 }
c@7 131
c@7 132 smoothedDifferentiator(spectrogram, 5); //make smoothLength a parameter!
c@7 133 halfWaveRectify(spectrogram);
c@7 134
c@7 135 for (int block = 0; block < m_numberOfBlocks; block++){
c@5 136 for (int band = 0; band < m_numberOfBands; band++){
c@7 137 int k = m_bandBoundaries[band];
c@7 138 int bandEnd = m_bandBoundaries[band+1];
c@7 139 m_bandSum[band] = 0;
c@5 140
c@7 141 while(k < bandEnd){
c@7 142 m_bandSum[band] += spectrogram[k][block];
c@7 143 k++;
c@5 144 }
c@5 145 }
c@5 146 float total = 0;
c@5 147 for(int band = 0; band < m_numberOfBands; band++){
c@7 148 total += m_bandSum[band];
c@5 149 }
c@7 150 data[block] = total/m_numberOfBands;
c@5 151 }
c@5 152
c@7 153 subtractLocalAverage(data);
c@5 154
c@5 155 return data;
c@7 156 }