annotate NoveltyCurveProcessor.cpp @ 20:de7213b35755

* Removed warnings of comparisons with ints and size_t
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Fri, 15 Aug 2014 15:17:28 +0100
parents 1e4c02ca8b81
children 99380ba63be6
rev   line source
c@5 1 //
c@17 2 // NoveltyCurveProcessor.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@11 9 //Spectrogram dimensions should be flipped?
c@11 10
c@14 11 #include "NoveltyCurveProcessor.h"
c@5 12 using namespace std;
c@5 13
c@14 14 NoveltyCurveProcessor::NoveltyCurveProcessor(const float &samplingFrequency, const size_t &fftLength, const size_t &numberOfBlocks, const size_t &compressionConstant) :
c@5 15 m_samplingFrequency(samplingFrequency),
c@7 16 m_fftLength(fftLength),
c@7 17 m_blockSize(fftLength/2 + 1),
c@5 18 m_numberOfBlocks(numberOfBlocks),
c@5 19 m_compressionConstant(compressionConstant),
c@5 20 m_numberOfBands(5),
c@13 21 m_pBandBoundaries(0),
c@13 22 m_pBandSum(0)
c@5 23 {
c@5 24 initialise();
c@5 25 }
c@5 26
c@14 27 NoveltyCurveProcessor::~NoveltyCurveProcessor(){
c@5 28 cleanup();
c@5 29 }
c@5 30
c@9 31 //allocate all space and set variable
c@5 32 void
c@14 33 NoveltyCurveProcessor::initialise(){
c@5 34
c@13 35 // for bandwise processing, the band is split into 5 bands. m_pBandBoundaries contains the upper and lower bin boundaries for each band.
c@13 36 m_pBandBoundaries = new int[m_numberOfBands+1];
c@13 37 m_pBandBoundaries[0] = 0;
c@13 38 for (unsigned int band = 1; band < m_numberOfBands; band++){
c@13 39 float lowFreq = 500*pow(2.5, (int)band-1);
c@13 40 m_pBandBoundaries[band] = m_fftLength*lowFreq/m_samplingFrequency;
c@5 41 }
c@13 42 m_pBandBoundaries[m_numberOfBands] = m_blockSize;
c@5 43
c@13 44 m_pBandSum = new float [m_numberOfBands];
c@5 45 }
c@5 46
c@9 47 //delete space allocated in initialise()
c@5 48 void
c@14 49 NoveltyCurveProcessor::cleanup(){
c@13 50 delete []m_pBandBoundaries;
c@13 51 m_pBandBoundaries = 0;
c@13 52 delete []m_pBandSum;
c@13 53 m_pBandSum = 0;
c@5 54 }
c@5 55
c@9 56 //calculate max of spectrogram
c@14 57 float NoveltyCurveProcessor::calculateMax(const vector< vector<float> > &spectrogram) const
c@13 58 {
c@5 59 float max = 0;
c@5 60
c@13 61 for (unsigned int j = 0; j < m_numberOfBlocks; j++){
c@13 62 for (unsigned int i = 0; i < m_blockSize; i++){
c@7 63 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
c@5 64 }
c@5 65 }
c@5 66
c@5 67 return max;
c@5 68 }
c@5 69
c@9 70 //subtract local average of novelty curve
c@9 71 //uses m_hannWindow as filter
c@14 72 void NoveltyCurveProcessor::subtractLocalAverage(vector<float> &noveltyCurve, const size_t &smoothLength) const
c@13 73 {
c@5 74 vector<float> localAverage(m_numberOfBlocks);
c@5 75
c@13 76 float * m_hannWindow = new float[smoothLength];
c@13 77 WindowFunction::hanning(m_hannWindow, smoothLength, true);
c@9 78
c@13 79 FIRFilter filter(m_numberOfBlocks, smoothLength);
c@15 80 filter.process(&noveltyCurve[0], m_hannWindow, &localAverage[0], FIRFilter::middle);
c@5 81
c@7 82 assert(noveltyCurve.size() == m_numberOfBlocks);
c@13 83 for (unsigned int i = 0; i < m_numberOfBlocks; i++){
c@5 84 noveltyCurve[i] -= localAverage[i];
c@5 85 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
c@5 86 }
c@9 87
c@11 88 delete []m_hannWindow;
c@13 89 m_hannWindow = 0;
c@5 90 }
c@5 91
c@9 92 //smoothed differentiator filter. Flips upper half of hanning window about y-axis to create coefficients.
c@14 93 void NoveltyCurveProcessor::smoothedDifferentiator(vector< vector<float> > &spectrogram, const size_t &smoothLength) const
c@13 94 {
c@7 95
c@7 96 float * diffHannWindow = new float [smoothLength];
c@7 97 WindowFunction::hanning(diffHannWindow, smoothLength, true);
c@7 98
c@7 99 if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0;
c@20 100 for(int i = (smoothLength+1)/2; i < (int)smoothLength; i++){
c@7 101 diffHannWindow[i] = -diffHannWindow[i];
c@7 102 }
c@7 103
c@11 104 FIRFilter smoothFilter(m_numberOfBlocks, smoothLength);
c@7 105
c@20 106 for (int i = 0; i < (int)m_blockSize; i++){
c@15 107 smoothFilter.process(&spectrogram[i][0], diffHannWindow, &spectrogram[i][0], FIRFilter::middle);
c@7 108 }
c@7 109 }
c@7 110
c@9 111 //half rectification (set negative to zero)
c@14 112 void NoveltyCurveProcessor::halfWaveRectify(vector< vector<float> > &spectrogram) const
c@13 113 {
c@20 114 for (int block = 0; block < (int)m_numberOfBlocks; block++){
c@20 115 for (int k = 0; k < (int)m_blockSize; k++){
c@7 116 if (spectrogram[k][block] < 0.0) spectrogram[k][block] = 0.0;
c@7 117 }
c@7 118 }
c@7 119 }
c@7 120
c@9 121 //process method
c@5 122 vector<float>
c@14 123 NoveltyCurveProcessor::spectrogramToNoveltyCurve(Spectrogram spectrogram) const
c@13 124 {
c@13 125 std::vector<float> noveltyCurve(m_numberOfBlocks);
c@7 126
c@14 127 //cout << spectrogram[0].size() << " : " << m_numberOfBlocks << endl;
c@7 128 assert(spectrogram.size() == m_blockSize);
c@7 129 assert(spectrogram[0].size() == m_numberOfBlocks);
c@5 130
c@9 131 //normalise and log spectrogram
c@5 132 float normaliseScale = calculateMax(spectrogram);
c@20 133 for (int block = 0; block < (int)m_numberOfBlocks; block++){
c@20 134 for (int k = 0; k < (int)m_blockSize; k++){
c@7 135 if(normaliseScale != 0.0) spectrogram[k][block] /= normaliseScale; //normalise
c@7 136 spectrogram[k][block] = log(1+m_compressionConstant*spectrogram[k][block]);
c@7 137 }
c@7 138 }
c@7 139
c@9 140 //smooted differentiator
c@7 141 smoothedDifferentiator(spectrogram, 5); //make smoothLength a parameter!
c@9 142 //halfwave rectification
c@7 143 halfWaveRectify(spectrogram);
c@7 144
c@9 145 //bandwise processing
c@20 146 for (int block = 0; block < (int)m_numberOfBlocks; block++){
c@20 147 for (int band = 0; band < (int)m_numberOfBands; band++){
c@13 148 int k = m_pBandBoundaries[band];
c@13 149 int bandEnd = m_pBandBoundaries[band+1];
c@13 150 m_pBandSum[band] = 0;
c@5 151
c@7 152 while(k < bandEnd){
c@13 153 m_pBandSum[band] += spectrogram[k][block];
c@7 154 k++;
c@5 155 }
c@5 156 }
c@5 157 float total = 0;
c@20 158 for(int band = 0; band < (int)m_numberOfBands; band++){
c@13 159 total += m_pBandSum[band];
c@5 160 }
c@13 161 noveltyCurve[block] = total/m_numberOfBands;
c@5 162 }
c@5 163
c@9 164 //subtract local averages
c@13 165 subtractLocalAverage(noveltyCurve, 65);
c@5 166
c@13 167 return noveltyCurve;
c@7 168 }