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