Mercurial > hg > vamp-tempogram
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 } |