Mercurial > hg > vamp-tempogram
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++){ |