c@5
|
1 //
|
c@5
|
2 // NoveltyCurve.cpp
|
c@5
|
3 // Tempogram
|
c@5
|
4 //
|
c@5
|
5 // Created by Carl Bussey on 10/07/2014.
|
c@5
|
6 // Copyright (c) 2014 Carl Bussey. All rights reserved.
|
c@5
|
7 //
|
c@5
|
8
|
c@5
|
9 #include <cmath>
|
c@5
|
10 #include <vector>
|
c@5
|
11 #include <iostream>
|
c@5
|
12 #include "FIRFilter.h"
|
c@5
|
13 #include "WindowFunction.h"
|
c@5
|
14 using namespace std;
|
c@5
|
15 #include "NoveltyCurve.h"
|
c@5
|
16
|
c@5
|
17 NoveltyCurve::NoveltyCurve(float samplingFrequency, int blockSize, int numberOfBlocks, int compressionConstant) :
|
c@5
|
18 m_samplingFrequency(samplingFrequency),
|
c@5
|
19 m_blockSize(blockSize),
|
c@5
|
20 m_numberOfBlocks(numberOfBlocks),
|
c@5
|
21 m_compressionConstant(compressionConstant),
|
c@5
|
22 m_numberOfBands(5),
|
c@5
|
23 m_bandBoundaries(NULL),
|
c@5
|
24 m_hannLength(65),
|
c@5
|
25 m_hannWindow(NULL),
|
c@5
|
26 m_bandSum(NULL)
|
c@5
|
27 {
|
c@5
|
28 initialise();
|
c@5
|
29 }
|
c@5
|
30
|
c@5
|
31 NoveltyCurve::~NoveltyCurve(){
|
c@5
|
32 cleanup();
|
c@5
|
33 }
|
c@5
|
34
|
c@5
|
35 void
|
c@5
|
36 NoveltyCurve::initialise(){
|
c@5
|
37 data = vector<float>(m_numberOfBlocks);
|
c@5
|
38
|
c@5
|
39 m_hannWindow = new float[m_hannLength];
|
c@5
|
40 WindowFunction::hanning(m_hannWindow, m_hannLength, true);
|
c@5
|
41
|
c@5
|
42 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable
|
c@5
|
43
|
c@5
|
44 m_bandBoundaries[0] = 0;
|
c@5
|
45 for (int band = 1; band < m_numberOfBands; band++){
|
c@5
|
46 float lowFreq = 500*pow(2.5, band-1);
|
c@5
|
47 m_bandBoundaries[band] = m_blockSize*lowFreq/m_samplingFrequency;
|
c@5
|
48 }
|
c@5
|
49 m_bandBoundaries[m_numberOfBands] = m_blockSize/2 + 1;
|
c@5
|
50
|
c@5
|
51 m_bandSum = new float * [m_numberOfBands];
|
c@5
|
52 for (int i = 0; i < m_numberOfBands; i++){
|
c@5
|
53 m_bandSum[i] = new float[m_numberOfBlocks];
|
c@5
|
54 }
|
c@5
|
55 }
|
c@5
|
56
|
c@5
|
57 void
|
c@5
|
58 NoveltyCurve::cleanup(){
|
c@5
|
59 delete []m_hannWindow;
|
c@5
|
60 m_hannWindow = NULL;
|
c@5
|
61 delete []m_bandBoundaries;
|
c@5
|
62 m_bandBoundaries = NULL;
|
c@5
|
63
|
c@5
|
64 for(int i = 0; i < m_numberOfBands; i++){
|
c@5
|
65 delete []m_bandSum[i];
|
c@5
|
66 m_bandSum[i] = NULL;
|
c@5
|
67 }
|
c@5
|
68 delete []m_bandSum;
|
c@5
|
69 m_bandSum = NULL;
|
c@5
|
70 }
|
c@5
|
71
|
c@5
|
72 float NoveltyCurve::calculateMax(float ** spectrogram){
|
c@5
|
73 int specLength = (m_blockSize/2 + 1);
|
c@5
|
74 float max = 0;
|
c@5
|
75
|
c@5
|
76 for (int j = 0; j < m_numberOfBlocks; j++){
|
c@5
|
77 for (int i = 0; i < specLength; i++){
|
c@5
|
78 max = max > spectrogram[i][j] ? max : spectrogram[i][j];
|
c@5
|
79 }
|
c@5
|
80 }
|
c@5
|
81
|
c@5
|
82 return max;
|
c@5
|
83 }
|
c@5
|
84
|
c@5
|
85 void NoveltyCurve::subtractLocalAverage(float * noveltyCurve){
|
c@5
|
86 vector<float> localAverage(m_numberOfBlocks);
|
c@5
|
87
|
c@5
|
88 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength);
|
c@5
|
89 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
|
c@5
|
90 delete filter;
|
c@5
|
91
|
c@5
|
92 for (int i = 0; i < m_numberOfBlocks; i++){
|
c@5
|
93 noveltyCurve[i] -= localAverage[i];
|
c@5
|
94 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
|
c@5
|
95 }
|
c@5
|
96 }
|
c@5
|
97
|
c@5
|
98 vector<float>
|
c@5
|
99 NoveltyCurve::spectrogramToNoveltyCurve(float ** spectrogram){
|
c@5
|
100
|
c@5
|
101 float normaliseScale = calculateMax(spectrogram);
|
c@5
|
102
|
c@5
|
103 for (int block = 0; block < m_numberOfBlocks; block++){
|
c@5
|
104
|
c@5
|
105 for (int band = 0; band < m_numberOfBands; band++){
|
c@5
|
106
|
c@5
|
107 int specIndex = m_bandBoundaries[band];
|
c@5
|
108 int bandEnd = m_bandBoundaries[band+1];
|
c@5
|
109
|
c@5
|
110 while(specIndex < bandEnd){
|
c@5
|
111
|
c@5
|
112 spectrogram[specIndex][block] /= normaliseScale; //normalise
|
c@5
|
113 spectrogram[specIndex][block] = log(1+m_compressionConstant*spectrogram[specIndex][block]);
|
c@5
|
114
|
c@5
|
115 int currentY = spectrogram[specIndex][block];
|
c@5
|
116 int prevBlock = block-1;
|
c@5
|
117 int previousY = prevBlock >= 0 ? spectrogram[specIndex][prevBlock] : 0;
|
c@5
|
118
|
c@5
|
119 if(currentY > previousY){
|
c@5
|
120 m_bandSum[band][block] += (currentY - previousY);
|
c@5
|
121 }
|
c@5
|
122
|
c@5
|
123 //cout << specIndex << endl;
|
c@5
|
124 specIndex++;
|
c@5
|
125 }
|
c@5
|
126 }
|
c@5
|
127
|
c@5
|
128 float total = 0;
|
c@5
|
129 for(int band = 0; band < m_numberOfBands; band++){
|
c@5
|
130 total += m_bandSum[band][block];
|
c@5
|
131 }
|
c@5
|
132 float average = total/m_numberOfBands;
|
c@5
|
133 data[block] = average;
|
c@5
|
134 }
|
c@5
|
135
|
c@5
|
136 subtractLocalAverage(&data[0]);
|
c@5
|
137
|
c@5
|
138 return data;
|
c@5
|
139 } |