Krotos Modules 3
Loading...
Searching...
No Matches
FrequencyDomainAnalysisFramework.cpp
Go to the documentation of this file.
1//=====================================================================================
7//=====================================================================================
8
10#include "Utilities.h"
11
12//=====================================================================================
14 : m_numMelCoefficients(40), m_numMelCepstralCoefficients(13), m_spectralFrameSize(analysisFrameSize)
15{
16 setSamplingFrequency(sampleRate);
17
19}
20
21//=====================================================================================
23{
24 m_samplingFrequency = fs;
25
26 // TODO:RD-52 that has to do with making sure that Mel Spectrum works @Chris
27 // Scott
28 m_melFrequencySpectrum.setSamplingFrequency(m_samplingFrequency);
29}
30
31//=====================================================================================
33{
34 jassert(m_spectralFrameSize > -1); // audio buffer size has not been set to a valid value
35
36 m_numMelCoefficients = numcoeffs;
37
38 m_melFrequencySpectrum.setParameters(m_spectralFrameSize, m_numMelCoefficients);
39}
40
41//=====================================================================================
43{
44 jassert(m_spectralFrameSize > -1); // audio buffer size has not been set to a valid value
45
46 m_numMelCepstralCoefficients = numcoeffs;
47
48 m_dct.setInputOutputSize(m_numMelCoefficients, m_numMelCepstralCoefficients);
49}
50
51//=====================================================================================
52void krotos::FrequencyDomainAnalysisFramework::setFrequencyVector(const std::vector<float>& freqVector)
53{
54
55 if (!m_freqVector.empty())
56 {
57 m_freqVector.clear();
58 }
59
60 m_freqVector = freqVector;
61 ;
62}
63
64//=====================================================================================
66{
67 jassert(m_samplingFrequency > -1); // Sampling frequency has not been set to a valid value
68 return m_samplingFrequency;
69}
70
71//=====================================================================================
76
77//=====================================================================================
79{
80 // Ensure your audio analysis buffer size is a positive power of two
81 assert(isPositivePowerOfTwo(m_spectralFrameSize));
82
83 // set prev magnitude spectrum for spectral flux
84 m_prevMagSpecSpectralFlux.resize(m_spectralFrameSize);
85
86 if (m_prevMagSpecSpectralFlux.size() > 0)
87 {
88 FloatVectorOperations::fill(&m_prevMagSpecSpectralFlux[0], 0.f, m_prevMagSpecSpectralFlux.size());
89 }
90
91 // set buffers for calculating complex spectral difference
92 m_prevMagSpecCSD.resize(m_spectralFrameSize);
93 m_prevPhase1CSD.resize(m_spectralFrameSize);
94 m_prevPhase2CSD.resize(m_spectralFrameSize);
95
96 if (m_prevMagSpecCSD.size() > 0)
97 {
98 FloatVectorOperations::fill(&m_prevMagSpecCSD[0], 0.f, m_prevMagSpecCSD.size());
99 }
100 if (m_prevPhase1CSD.size() > 0)
101 {
102 FloatVectorOperations::fill(&m_prevPhase1CSD[0], 0.f, m_prevPhase1CSD.size());
103 }
104 if (m_prevPhase2CSD.size() > 0)
105 {
106 FloatVectorOperations::fill(&m_prevPhase2CSD[0], 0.f, m_prevPhase2CSD.size());
107 }
108
109 setNumberOfMelFrequencyCoefficients(m_numMelCoefficients);
110
111 setNumberOfMelFrequencyCepstralCoefficients(m_numMelCepstralCoefficients);
112}
113
114//=====================================================================================
116{
117 m_spectralFrame = spectralFrame;
118}
119
120//=====================================================================================
122{
123 jassert(m_samplingFrequency > -1); // Sampling frequency has not been set to a valid value
124
125 float currentMax{0.0f};
126 int currentMaxIndex{0};
127 for (int i = 0; i < m_spectralFrame.size(); i++)
128 {
129 if (std::fabsf(m_spectralFrame[i]) > currentMax)
130 {
131 currentMax = m_spectralFrame[i];
132 currentMaxIndex = i;
133 }
134 }
135
136 return (float)currentMaxIndex * (float)m_samplingFrequency / (float)m_spectralFrameSize;
137}
138
139//=====================================================================================
141{
142 return m_melFrequencySpectrum.calculateMelSpectrum(m_spectralFrame);
143}
144
145//=====================================================================================
147{
148 // To-do: check if mel spectrum has already been computed
149 auto melSpec = m_melFrequencySpectrum.calculateMelSpectrum(m_spectralFrame);
150
151 // log transform
152 for (auto& value : melSpec)
153 value = std::logf(std::max(value, 1e-5f));
154
155 return m_dct.calculateDCT(melSpec);
156}
157
158//=====================================================================================
160{
161 jassert(m_samplingFrequency > -1); // Sampling frequency has not been set to a valid value
162
163 float weightedSum = 0;
164 float sum = 0;
165
166 for (int i = 0; i < m_spectralFrame.size(); i++) // Careful :: never use m_specFrameSize they can be different!!!
167 {
168 float centreFrequency = m_freqVector[i];
169
170 weightedSum += centreFrequency * m_spectralFrame[i];
171
172 sum += m_spectralFrame[i];
173 }
174
175 if (sum == 0.0)
176 {
177 return 0.0;
178 }
179 else
180 {
181 return weightedSum / sum;
182 }
183}
184
185//=====================================================================================
187{
188 float logSum = 0;
189 float sum = 0;
190 const float eps = 2.2204e-16f; // MATLAB epsilon
191
192 for (int i = 0; i < m_spectralFrame.size(); i++)
193 {
194 // we add 1 here to stop zeros making the logs -inf
195 //@Chris Scott is gonna rectify the calculation here to reflect Python
196 float sample = m_spectralFrame[i] + eps;
197
198 logSum += logf(sample);
199 sum += sample;
200 }
201
202 logSum = logSum / (float)m_spectralFrame.size();
203 sum = sum / (float)m_spectralFrame.size();
204
205 logSum = expf(logSum);
206
207 if (sum == 0)
208 {
209 return 0.0;
210 }
211 else
212 {
213 return logSum / (sum + eps);
214 }
215}
216
217//=====================================================================================
219{
220 jassert(m_samplingFrequency > -1); // Sampling frequency has not been set to a valid value
221
222 float resolution = (float)m_samplingFrequency / (float)m_spectralFrameSize;
223 float centroid = getSpectralCentroid(); // Calculate the spectral centroid
224
225 float sum = 0;
226 float magnitudeSum = 0;
227
228 for (int i = 0; i < m_spectralFrame.size(); i++)
229 {
230 float centreFrequency = resolution * (float)i;
231 float deviation = centreFrequency - centroid; // Calculate the deviation from the centroid
232 sum += deviation * deviation * m_spectralFrame[i]; // Accumulate the squared deviation multiplied by
233 // the magnitude
234 magnitudeSum += m_spectralFrame[i]; // Accumulate the magnitudes
235 }
236
237 if (magnitudeSum == 0.0)
238 {
239 return 0.0;
240 }
241 else
242 {
243 float spread = std::sqrt(sum / magnitudeSum); // Calculate the square root of the
244 // average squared deviation
245 return spread;
246 }
247}
248
249//=====================================================================================
251{
252 jassert(m_samplingFrequency > -1); // Sampling frequency has not been set to a valid value
253
254 float resolution = (float)m_samplingFrequency / (float)m_spectralFrameSize;
255
256 float sumXY = 0;
257 float sumX = 0;
258 float sumY = 0;
259 float sumX2 = 0;
260
261 for (int i = 0; i < m_spectralFrame.size(); i++)
262 {
263 float centreFrequency = resolution * (float)i;
264 float magnitude = m_spectralFrame[i];
265
266 sumXY += centreFrequency * magnitude;
267 sumX += centreFrequency;
268 sumY += magnitude;
269 sumX2 += centreFrequency * centreFrequency;
270 }
271
272 float n = (float)m_spectralFrame.size();
273 float slope = (n * sumXY - sumX * sumY) / ((n * sumX2 - sumX * sumX) * sumY);
274
275 return slope;
276}
277
278//=====================================================================================
280{
281 // sum the spectrum
282 float spectralSum = 0;
283
284 for (int i = 0; i < m_spectralFrameSize; i++)
285 {
286 spectralSum += m_spectralFrame[i];
287 }
288
289 // calculate the rolloff threshold;
290 float rolloffThreshold = spectralSum * 0.85f;
291
292 // define the rolloff index
293 float rolloffIndex = 0;
294
295 // reset the spectral sum
296 spectralSum = 0;
297
298 for (int i = 0; i < m_spectralFrameSize; i++)
299 {
300 // sum the spectrum again
301 spectralSum += m_spectralFrame[i];
302
303 // if we exceed the rolloff threshold
304 if (spectralSum > rolloffThreshold)
305 {
306 // store the index and break
307 rolloffIndex = (float)i;
308 break;
309 }
310 }
311
312 // calclulate spectral rolloff normalised by the length of the magnitude
313 // spectrum
314 float spectralRolloff = rolloffIndex / (float)m_spectralFrameSize;
315
316 return spectralRolloff;
317}
318
319//=====================================================================================
321{
322 float sum = 0;
323
324 for (int i = 0; i < m_spectralFrameSize; i++)
325 {
326 float difference = fabs(m_spectralFrame[i] - m_prevMagSpecSpectralFlux[i]);
327
328 sum += difference;
329
330 m_prevMagSpecSpectralFlux[i] = m_spectralFrame[i];
331 }
332
333 return sum;
334}
335
336//=====================================================================================
338{
339 float energy = 0.0f;
340
341 for (int i = 0; i < m_spectralFrameSize; ++i)
342 {
343 float amplitude = m_spectralFrame[i];
344 energy += amplitude * amplitude;
345 }
346
347 return energy;
348}
349
350//=====================================================================================
352{
353 float sum = 0;
354
355 for (int i = 0; i < m_spectralFrameSize; i++)
356 {
357 sum += (m_spectralFrame[i] * (float)i);
358 }
359
360 return sum;
361}
362
363//=====================================================================================
367// float
368// krotos::FrequencyDomainAnalysisFramework::getComplexSpectralDifference()
369//{
370// checkFFTHasBeenCalculated();
371//
372// float phaseDeviation;
373// float complexSpectralDifference;
374//
375// complexSpectralDifference = 0;
376//
377// for (int i = 0;i < m_spectralFrameSize;i++)
378// {
379// float phaseValue = atan2(m_fft.imag[i],m_fft.real[i]);
380//
381// phaseDeviation = phaseValue - (2*m_prevPhase1CSD[i]) +
382// m_prevPhase2CSD[i];
383//
384// //phaseDeviation = phaseWrap(phaseDeviation);
385//
386// float magnitudeDifference = m_fft.magnitudeSpectrum[i] -
387// m_prevMagSpecCSD[i];
388//
389// float phaseDifference =
390// -m_fft.magnitudeSpectrum[i]*sin(phaseDeviation);
391//
392// complexSpectralDifference +=
393// sqrt((magnitudeDifference*magnitudeDifference) +
394// (phaseDifference*phaseDifference));
395//
396// m_prevPhase2CSD[i] = m_prevPhase1CSD[i];
397// m_prevPhase1CSD[i] = phaseValue;
398// m_prevMagSpecCSD[i] = m_fft.magnitudeSpectrum[i];
399// }
400//
401// return complexSpectralDifference;
402//}
403
404//=====================================================================================
406{
407 float denominatorSum = 0;
408 float numeratorSum = 0;
409
410 for (int i = 0; i < m_spectralFrameSize; i++)
411 {
412 float k = (float)i;
413 numeratorSum += powf(k, static_cast<float>(n)) * m_spectralFrame[i];
414
415 denominatorSum += m_spectralFrame[i];
416 }
417
418 if (denominatorSum == 0)
419 {
420 return 0.0;
421 }
422 else
423 {
424 return numeratorSum / denominatorSum;
425 }
426}
427
428//=====================================================================================
430{
431 float u1 = calculateSpectralMoment(1);
432 float u2 = calculateSpectralMoment(2);
433 float u3 = calculateSpectralMoment(3);
434 float u4 = calculateSpectralMoment(4);
435
436 float spread = sqrt(u2 - u1 * u1);
437
438 float x = -3 * powf(u1, 4) + 6 * u1 * u2 + 4 * u1 * u3 + u4;
439 float y = powf(spread, 4);
440
441 float kurtosis;
442
443 if (y == 0)
444 {
445 kurtosis = 0.0;
446 }
447 else
448 {
449 kurtosis = (x / y) - 3;
450 }
451
452 return kurtosis;
453}
int getNumberOfMelFrequencyCepstralCoefficients()
Definition FrequencyDomainAnalysisFramework.cpp:72
float getHighFreqencyContentOnsetDectionFunction()
Definition FrequencyDomainAnalysisFramework.cpp:351
float getSpectralFlux()
Definition FrequencyDomainAnalysisFramework.cpp:320
void setNumberOfMelFrequencyCepstralCoefficients(int numCoeffs)
Definition FrequencyDomainAnalysisFramework.cpp:42
void setSamplingFrequency(int fs)
Definition FrequencyDomainAnalysisFramework.cpp:22
float getSpectralFlatness()
Definition FrequencyDomainAnalysisFramework.cpp:186
float getSpectralKurtosis()
Definition FrequencyDomainAnalysisFramework.cpp:429
std::vector< float > getMelSpectrum()
Definition FrequencyDomainAnalysisFramework.cpp:140
void setNumberOfMelFrequencyCoefficients(int numCoeffs)
Definition FrequencyDomainAnalysisFramework.cpp:32
int getSamplingFrequency()
Definition FrequencyDomainAnalysisFramework.cpp:65
float calculateSpectralMoment(int n)
Definition FrequencyDomainAnalysisFramework.cpp:405
float getSpectralRolloff()
Definition FrequencyDomainAnalysisFramework.cpp:279
FrequencyDomainAnalysisFramework(int analysisFrameSize, int sampleRate)
Definition FrequencyDomainAnalysisFramework.cpp:13
void setFrequencyVector(const std::vector< float > &freqVector)
Definition FrequencyDomainAnalysisFramework.cpp:52
float getSpectralSlope()
Definition FrequencyDomainAnalysisFramework.cpp:250
std::vector< float > getMFCC()
Definition FrequencyDomainAnalysisFramework.cpp:146
void initialiseSpectralAnalysisAlgorithms()
Definition FrequencyDomainAnalysisFramework.cpp:78
float getSpectralCentroid()
Definition FrequencyDomainAnalysisFramework.cpp:159
float getFreqOfLoudestPartial()
Definition FrequencyDomainAnalysisFramework.cpp:121
void setSpectralFrame(std::vector< float > spectralFrame)
Definition FrequencyDomainAnalysisFramework.cpp:115
float getFrameEnergy()
Definition FrequencyDomainAnalysisFramework.cpp:337
float getSpectralSpread()
Definition FrequencyDomainAnalysisFramework.cpp:218
bool isPositivePowerOfTwo(int x)
Definition Utilities.h:14