comparison NoveltyCurveProcessor.cpp @ 22:99380ba63be6

* Changed input of NoveltyCurve::spectrogramToNoveltyCurve() from transposed spe ctrogram to spectrogram * Collect spectrogram from process(), not transposed spectrogram * allowed OctaveDivider parameter to be any value in range, despite number of binumber of values in the range
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Tue, 19 Aug 2014 16:52:19 +0100
parents de7213b35755
children 7d36c742a183
comparison
equal deleted inserted replaced
21:12b952286959 22:99380ba63be6
9 //Spectrogram dimensions should be flipped? 9 //Spectrogram dimensions should be flipped?
10 10
11 #include "NoveltyCurveProcessor.h" 11 #include "NoveltyCurveProcessor.h"
12 using namespace std; 12 using namespace std;
13 13
14 NoveltyCurveProcessor::NoveltyCurveProcessor(const float &samplingFrequency, const size_t &fftLength, const size_t &numberOfBlocks, const size_t &compressionConstant) : 14 NoveltyCurveProcessor::NoveltyCurveProcessor(const float &samplingFrequency, const size_t &fftLength, const size_t &compressionConstant) :
15 m_samplingFrequency(samplingFrequency), 15 m_samplingFrequency(samplingFrequency),
16 m_fftLength(fftLength), 16 m_fftLength(fftLength),
17 m_blockSize(fftLength/2 + 1), 17 m_blockSize(fftLength/2 + 1),
18 m_numberOfBlocks(numberOfBlocks),
19 m_compressionConstant(compressionConstant), 18 m_compressionConstant(compressionConstant),
20 m_numberOfBands(5), 19 m_numberOfBands(5),
21 m_pBandBoundaries(0), 20 m_pBandBoundaries(0),
22 m_pBandSum(0) 21 m_pBandSum(0)
23 { 22 {
52 delete []m_pBandSum; 51 delete []m_pBandSum;
53 m_pBandSum = 0; 52 m_pBandSum = 0;
54 } 53 }
55 54
56 //calculate max of spectrogram 55 //calculate max of spectrogram
57 float NoveltyCurveProcessor::calculateMax(const vector< vector<float> > &spectrogram) const 56 float NoveltyCurveProcessor::calculateMax(const Spectrogram &spectrogram) const
58 { 57 {
59 float max = 0; 58 float max = 0;
60 59
61 for (unsigned int j = 0; j < m_numberOfBlocks; j++){ 60 int length = spectrogram.size();
62 for (unsigned int i = 0; i < m_blockSize; i++){ 61 int height = spectrogram[0].size();
62
63 for (int i = 0; i < length; i++){
64 for (int j = 0; j < height; j++){
63 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]); 65 max = max > fabs(spectrogram[i][j]) ? max : fabs(spectrogram[i][j]);
64 } 66 }
65 } 67 }
66 68
67 return max; 69 return max;
69 71
70 //subtract local average of novelty curve 72 //subtract local average of novelty curve
71 //uses m_hannWindow as filter 73 //uses m_hannWindow as filter
72 void NoveltyCurveProcessor::subtractLocalAverage(vector<float> &noveltyCurve, const size_t &smoothLength) const 74 void NoveltyCurveProcessor::subtractLocalAverage(vector<float> &noveltyCurve, const size_t &smoothLength) const
73 { 75 {
74 vector<float> localAverage(m_numberOfBlocks); 76 int numberOfBlocks = noveltyCurve.size();
77 vector<float> localAverage(numberOfBlocks);
75 78
76 float * m_hannWindow = new float[smoothLength]; 79 float * m_hannWindow = new float[smoothLength];
77 WindowFunction::hanning(m_hannWindow, smoothLength, true); 80 WindowFunction::hanning(m_hannWindow, smoothLength, true);
78 81
79 FIRFilter filter(m_numberOfBlocks, smoothLength); 82 FIRFilter filter(numberOfBlocks, smoothLength);
80 filter.process(&noveltyCurve[0], m_hannWindow, &localAverage[0], FIRFilter::middle); 83 filter.process(&noveltyCurve[0], m_hannWindow, &localAverage[0], FIRFilter::middle);
81 84
82 assert(noveltyCurve.size() == m_numberOfBlocks); 85 for (int i = 0; i < numberOfBlocks; i++){
83 for (unsigned int i = 0; i < m_numberOfBlocks; i++){
84 noveltyCurve[i] -= localAverage[i]; 86 noveltyCurve[i] -= localAverage[i];
85 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; 87 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
86 } 88 }
87 89
88 delete []m_hannWindow; 90 delete []m_hannWindow;
89 m_hannWindow = 0; 91 m_hannWindow = 0;
90 } 92 }
91 93
92 //smoothed differentiator filter. Flips upper half of hanning window about y-axis to create coefficients. 94 //smoothed differentiator filter. Flips upper half of hanning window about y-axis to create coefficients.
93 void NoveltyCurveProcessor::smoothedDifferentiator(vector< vector<float> > &spectrogram, const size_t &smoothLength) const 95 void NoveltyCurveProcessor::smoothedDifferentiator(SpectrogramTransposed &spectrogramTransposed, const size_t &smoothLength) const
94 { 96 {
97
98 int numberOfBlocks = spectrogramTransposed[0].size();
95 99
96 float * diffHannWindow = new float [smoothLength]; 100 float * diffHannWindow = new float [smoothLength];
97 WindowFunction::hanning(diffHannWindow, smoothLength, true); 101 WindowFunction::hanning(diffHannWindow, smoothLength, true);
98 102
99 if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0; 103 if(smoothLength%2) diffHannWindow[(smoothLength+1)/2 - 1] = 0;
100 for(int i = (smoothLength+1)/2; i < (int)smoothLength; i++){ 104 for(int i = (smoothLength+1)/2; i < (int)smoothLength; i++){
101 diffHannWindow[i] = -diffHannWindow[i]; 105 diffHannWindow[i] = -diffHannWindow[i];
102 } 106 }
103 107
104 FIRFilter smoothFilter(m_numberOfBlocks, smoothLength); 108 FIRFilter smoothFilter(numberOfBlocks, smoothLength);
105 109
106 for (int i = 0; i < (int)m_blockSize; i++){ 110 for (int i = 0; i < (int)m_blockSize; i++){
107 smoothFilter.process(&spectrogram[i][0], diffHannWindow, &spectrogram[i][0], FIRFilter::middle); 111 smoothFilter.process(&spectrogramTransposed[i][0], diffHannWindow, &spectrogramTransposed[i][0], FIRFilter::middle);
108 } 112 }
109 } 113 }
110 114
111 //half rectification (set negative to zero) 115 //half rectification (set negative to zero)
112 void NoveltyCurveProcessor::halfWaveRectify(vector< vector<float> > &spectrogram) const 116 void NoveltyCurveProcessor::halfWaveRectify(SpectrogramTransposed &spectrogramTransposed) const
113 { 117 {
114 for (int block = 0; block < (int)m_numberOfBlocks; block++){ 118 int numberOfBlocks = spectrogramTransposed[0].size();
119
120 for (int block = 0; block < (int)numberOfBlocks; block++){
115 for (int k = 0; k < (int)m_blockSize; k++){ 121 for (int k = 0; k < (int)m_blockSize; k++){
116 if (spectrogram[k][block] < 0.0) spectrogram[k][block] = 0.0; 122 if (spectrogramTransposed[k][block] < 0.0) spectrogramTransposed[k][block] = 0.0;
117 } 123 }
118 } 124 }
119 } 125 }
120 126
121 //process method 127 //process method
122 vector<float> 128 vector<float>
123 NoveltyCurveProcessor::spectrogramToNoveltyCurve(Spectrogram spectrogram) const 129 NoveltyCurveProcessor::spectrogramToNoveltyCurve(const Spectrogram &spectrogram) const //make argument const &
124 { 130 {
125 std::vector<float> noveltyCurve(m_numberOfBlocks); 131 int numberOfBlocks = spectrogram.size();
126 132 std::vector<float> noveltyCurve(numberOfBlocks);
127 //cout << spectrogram[0].size() << " : " << m_numberOfBlocks << endl; 133 SpectrogramTransposed spectrogramTransposed(spectrogram[0].size(), vector<float>(spectrogram.size()));
128 assert(spectrogram.size() == m_blockSize);
129 assert(spectrogram[0].size() == m_numberOfBlocks);
130 134
131 //normalise and log spectrogram 135 //normalise and log spectrogram
132 float normaliseScale = calculateMax(spectrogram); 136 float normaliseScale = calculateMax(spectrogram);
133 for (int block = 0; block < (int)m_numberOfBlocks; block++){ 137 for (int block = 0; block < (int)numberOfBlocks; block++){
134 for (int k = 0; k < (int)m_blockSize; k++){ 138 for (int k = 0; k < (int)m_blockSize; k++){
135 if(normaliseScale != 0.0) spectrogram[k][block] /= normaliseScale; //normalise 139 spectrogramTransposed[k][block] = log(1+m_compressionConstant*spectrogram[block][k]);
136 spectrogram[k][block] = log(1+m_compressionConstant*spectrogram[k][block]); 140 if(normaliseScale != 0.0) spectrogramTransposed[k][block] /= normaliseScale; //normalise
137 } 141 }
138 } 142 }
139 143
140 //smooted differentiator 144 //smooted differentiator
141 smoothedDifferentiator(spectrogram, 5); //make smoothLength a parameter! 145 smoothedDifferentiator(spectrogramTransposed, 5); //make smoothLength a parameter!
142 //halfwave rectification 146 //halfwave rectification
143 halfWaveRectify(spectrogram); 147 halfWaveRectify(spectrogramTransposed);
144 148
145 //bandwise processing 149 //bandwise processing
146 for (int block = 0; block < (int)m_numberOfBlocks; block++){ 150 for (int block = 0; block < (int)numberOfBlocks; block++){
147 for (int band = 0; band < (int)m_numberOfBands; band++){ 151 for (int band = 0; band < (int)m_numberOfBands; band++){
148 int k = m_pBandBoundaries[band]; 152 int k = m_pBandBoundaries[band];
149 int bandEnd = m_pBandBoundaries[band+1]; 153 int bandEnd = m_pBandBoundaries[band+1];
150 m_pBandSum[band] = 0; 154 m_pBandSum[band] = 0;
151 155
152 while(k < bandEnd){ 156 while(k < bandEnd){
153 m_pBandSum[band] += spectrogram[k][block]; 157 m_pBandSum[band] += spectrogramTransposed[k][block];
154 k++; 158 k++;
155 } 159 }
156 } 160 }
157 float total = 0; 161 float total = 0;
158 for(int band = 0; band < (int)m_numberOfBands; band++){ 162 for(int band = 0; band < (int)m_numberOfBands; band++){