comparison 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
comparison
equal deleted inserted replaced
6:14a143a2c4c9 7:21147df9cb2d
4 // 4 //
5 // Created by Carl Bussey on 10/07/2014. 5 // Created by Carl Bussey on 10/07/2014.
6 // Copyright (c) 2014 Carl Bussey. All rights reserved. 6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
7 // 7 //
8 8
9 #include <cmath> 9 #include "NoveltyCurve.h"
10 #include <vector>
11 #include <iostream>
12 #include "FIRFilter.h"
13 #include "WindowFunction.h"
14 using namespace std; 10 using namespace std;
15 #include "NoveltyCurve.h"
16 11
17 NoveltyCurve::NoveltyCurve(float samplingFrequency, int blockSize, int numberOfBlocks, int compressionConstant) : 12 NoveltyCurve::NoveltyCurve(float samplingFrequency, int fftLength, int numberOfBlocks, int compressionConstant) :
18 m_samplingFrequency(samplingFrequency), 13 m_samplingFrequency(samplingFrequency),
19 m_blockSize(blockSize), 14 m_fftLength(fftLength),
15 m_blockSize(fftLength/2 + 1),
20 m_numberOfBlocks(numberOfBlocks), 16 m_numberOfBlocks(numberOfBlocks),
21 m_compressionConstant(compressionConstant), 17 m_compressionConstant(compressionConstant),
22 m_numberOfBands(5), 18 m_numberOfBands(5),
23 m_bandBoundaries(NULL), 19 m_bandBoundaries(NULL),
24 m_hannLength(65), 20 m_hannLength(65),
42 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable 38 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable
43 39
44 m_bandBoundaries[0] = 0; 40 m_bandBoundaries[0] = 0;
45 for (int band = 1; band < m_numberOfBands; band++){ 41 for (int band = 1; band < m_numberOfBands; band++){
46 float lowFreq = 500*pow(2.5, band-1); 42 float lowFreq = 500*pow(2.5, band-1);
47 m_bandBoundaries[band] = m_blockSize*lowFreq/m_samplingFrequency; 43 m_bandBoundaries[band] = m_fftLength*lowFreq/m_samplingFrequency;
48 } 44 }
49 m_bandBoundaries[m_numberOfBands] = m_blockSize/2 + 1; 45 m_bandBoundaries[m_numberOfBands] = m_blockSize;
50 46
51 m_bandSum = new float * [m_numberOfBands]; 47 m_bandSum = new float [m_numberOfBands];
52 for (int i = 0; i < m_numberOfBands; i++){
53 m_bandSum[i] = new float[m_numberOfBlocks];
54 }
55 } 48 }
56 49
57 void 50 void
58 NoveltyCurve::cleanup(){ 51 NoveltyCurve::cleanup(){
59 delete []m_hannWindow; 52 delete []m_hannWindow;
60 m_hannWindow = NULL; 53 m_hannWindow = NULL;
61 delete []m_bandBoundaries; 54 delete []m_bandBoundaries;
62 m_bandBoundaries = NULL; 55 m_bandBoundaries = NULL;
63
64 for(int i = 0; i < m_numberOfBands; i++){
65 delete []m_bandSum[i];
66 m_bandSum[i] = NULL;
67 }
68 delete []m_bandSum; 56 delete []m_bandSum;
69 m_bandSum = NULL; 57 m_bandSum = NULL;
70 } 58 }
71 59
72 float NoveltyCurve::calculateMax(float ** spectrogram){ 60 float NoveltyCurve::calculateMax(vector< vector<float> > &spectrogram){
73 int specLength = (m_blockSize/2 + 1);
74 float max = 0; 61 float max = 0;
75 62
76 for (int j = 0; j < m_numberOfBlocks; j++){ 63 for (int j = 0; j < m_numberOfBlocks; j++){
77 for (int i = 0; i < specLength; i++){ 64 for (int i = 0; i < m_blockSize; i++){
78 max = max > spectrogram[i][j] ? max : spectrogram[i][j]; 65 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
79 } 66 }
80 } 67 }
81 68
82 return max; 69 return max;
83 } 70 }
84 71
85 void NoveltyCurve::subtractLocalAverage(float * noveltyCurve){ 72 void NoveltyCurve::subtractLocalAverage(vector<float> &noveltyCurve){
86 vector<float> localAverage(m_numberOfBlocks); 73 vector<float> localAverage(m_numberOfBlocks);
87 74
88 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength); 75 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength);
89 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]); 76 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
90 delete filter; 77 delete filter;
78 filter = NULL;
91 79
80 assert(noveltyCurve.size() == m_numberOfBlocks);
92 for (int i = 0; i < m_numberOfBlocks; i++){ 81 for (int i = 0; i < m_numberOfBlocks; i++){
93 noveltyCurve[i] -= localAverage[i]; 82 noveltyCurve[i] -= localAverage[i];
94 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; 83 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
95 } 84 }
96 } 85 }
97 86
87 void NoveltyCurve::smoothedDifferentiator(vector< vector<float> > &spectrogram, int smoothLength){
88
89 //need to make new hannWindow!!
90 float * diffHannWindow = new float [smoothLength];
91 WindowFunction::hanning(diffHannWindow, smoothLength, true);
92
93 if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0;
94 for(int i = (smoothLength+1)/2; i < smoothLength; i++){
95 diffHannWindow[i] = -diffHannWindow[i];
96 }
97
98 FIRFilter *smoothFilter = new FIRFilter(m_numberOfBlocks, smoothLength);
99
100 for (int i = 0; i < m_blockSize; i++){
101 smoothFilter->process(&spectrogram[i][0], diffHannWindow, &spectrogram[i][0]);
102 }
103
104 delete smoothFilter;
105 smoothFilter = NULL;
106 }
107
108 void NoveltyCurve::halfWaveRectify(vector< vector<float> > &spectrogram){ //should this return spectrogram??
109
110 for (int block = 0; block < m_numberOfBlocks; block++){
111 for (int k = 0; k < m_blockSize; k++){
112 if (spectrogram[k][block] < 0.0) spectrogram[k][block] = 0.0;
113 }
114 }
115 }
116
98 vector<float> 117 vector<float>
99 NoveltyCurve::spectrogramToNoveltyCurve(float ** spectrogram){ 118 NoveltyCurve::spectrogramToNoveltyCurve(vector< vector<float> > &spectrogram){
119
120 assert(spectrogram.size() == m_blockSize);
121 assert(spectrogram[0].size() == m_numberOfBlocks);
100 122
101 float normaliseScale = calculateMax(spectrogram); 123 float normaliseScale = calculateMax(spectrogram);
102 124
103 for (int block = 0; block < m_numberOfBlocks; block++){ 125 for (int block = 0; block < m_numberOfBlocks; block++){
104 126 for (int k = 0; k < m_blockSize; k++){
127 if(normaliseScale != 0.0) spectrogram[k][block] /= normaliseScale; //normalise
128 spectrogram[k][block] = log(1+m_compressionConstant*spectrogram[k][block]);
129 }
130 }
131
132 smoothedDifferentiator(spectrogram, 5); //make smoothLength a parameter!
133 halfWaveRectify(spectrogram);
134
135 for (int block = 0; block < m_numberOfBlocks; block++){
105 for (int band = 0; band < m_numberOfBands; band++){ 136 for (int band = 0; band < m_numberOfBands; band++){
137 int k = m_bandBoundaries[band];
138 int bandEnd = m_bandBoundaries[band+1];
139 m_bandSum[band] = 0;
106 140
107 int specIndex = m_bandBoundaries[band]; 141 while(k < bandEnd){
108 int bandEnd = m_bandBoundaries[band+1]; 142 m_bandSum[band] += spectrogram[k][block];
109 143 k++;
110 while(specIndex < bandEnd){
111
112 spectrogram[specIndex][block] /= normaliseScale; //normalise
113 spectrogram[specIndex][block] = log(1+m_compressionConstant*spectrogram[specIndex][block]);
114
115 int currentY = spectrogram[specIndex][block];
116 int prevBlock = block-1;
117 int previousY = prevBlock >= 0 ? spectrogram[specIndex][prevBlock] : 0;
118
119 if(currentY > previousY){
120 m_bandSum[band][block] += (currentY - previousY);
121 }
122
123 //cout << specIndex << endl;
124 specIndex++;
125 } 144 }
126 } 145 }
127
128 float total = 0; 146 float total = 0;
129 for(int band = 0; band < m_numberOfBands; band++){ 147 for(int band = 0; band < m_numberOfBands; band++){
130 total += m_bandSum[band][block]; 148 total += m_bandSum[band];
131 } 149 }
132 float average = total/m_numberOfBands; 150 data[block] = total/m_numberOfBands;
133 data[block] = average;
134 } 151 }
135 152
136 subtractLocalAverage(&data[0]); 153 subtractLocalAverage(data);
137 154
138 return data; 155 return data;
139 } 156 }