comparison NoveltyCurve.cpp @ 5:8d7e336b41e9

Adding NoveltyCurve.*
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Tue, 05 Aug 2014 15:59:15 +0100
parents
children 21147df9cb2d
comparison
equal deleted inserted replaced
4:597f033fa7a2 5:8d7e336b41e9
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 #include <cmath>
10 #include <vector>
11 #include <iostream>
12 #include "FIRFilter.h"
13 #include "WindowFunction.h"
14 using namespace std;
15 #include "NoveltyCurve.h"
16
17 NoveltyCurve::NoveltyCurve(float samplingFrequency, int blockSize, int numberOfBlocks, int compressionConstant) :
18 m_samplingFrequency(samplingFrequency),
19 m_blockSize(blockSize),
20 m_numberOfBlocks(numberOfBlocks),
21 m_compressionConstant(compressionConstant),
22 m_numberOfBands(5),
23 m_bandBoundaries(NULL),
24 m_hannLength(65),
25 m_hannWindow(NULL),
26 m_bandSum(NULL)
27 {
28 initialise();
29 }
30
31 NoveltyCurve::~NoveltyCurve(){
32 cleanup();
33 }
34
35 void
36 NoveltyCurve::initialise(){
37 data = vector<float>(m_numberOfBlocks);
38
39 m_hannWindow = new float[m_hannLength];
40 WindowFunction::hanning(m_hannWindow, m_hannLength, true);
41
42 m_bandBoundaries = new int[m_numberOfBands+1]; //make index variable
43
44 m_bandBoundaries[0] = 0;
45 for (int band = 1; band < m_numberOfBands; band++){
46 float lowFreq = 500*pow(2.5, band-1);
47 m_bandBoundaries[band] = m_blockSize*lowFreq/m_samplingFrequency;
48 }
49 m_bandBoundaries[m_numberOfBands] = m_blockSize/2 + 1;
50
51 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 }
56
57 void
58 NoveltyCurve::cleanup(){
59 delete []m_hannWindow;
60 m_hannWindow = NULL;
61 delete []m_bandBoundaries;
62 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;
69 m_bandSum = NULL;
70 }
71
72 float NoveltyCurve::calculateMax(float ** spectrogram){
73 int specLength = (m_blockSize/2 + 1);
74 float max = 0;
75
76 for (int j = 0; j < m_numberOfBlocks; j++){
77 for (int i = 0; i < specLength; i++){
78 max = max > spectrogram[i][j] ? max : spectrogram[i][j];
79 }
80 }
81
82 return max;
83 }
84
85 void NoveltyCurve::subtractLocalAverage(float * noveltyCurve){
86 vector<float> localAverage(m_numberOfBlocks);
87
88 FIRFilter *filter = new FIRFilter(m_numberOfBlocks, m_hannLength);
89 filter->process(&noveltyCurve[0], m_hannWindow, &localAverage[0]);
90 delete filter;
91
92 for (int i = 0; i < m_numberOfBlocks; i++){
93 noveltyCurve[i] -= localAverage[i];
94 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0;
95 }
96 }
97
98 vector<float>
99 NoveltyCurve::spectrogramToNoveltyCurve(float ** spectrogram){
100
101 float normaliseScale = calculateMax(spectrogram);
102
103 for (int block = 0; block < m_numberOfBlocks; block++){
104
105 for (int band = 0; band < m_numberOfBands; band++){
106
107 int specIndex = m_bandBoundaries[band];
108 int bandEnd = m_bandBoundaries[band+1];
109
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 }
126 }
127
128 float total = 0;
129 for(int band = 0; band < m_numberOfBands; band++){
130 total += m_bandSum[band][block];
131 }
132 float average = total/m_numberOfBands;
133 data[block] = average;
134 }
135
136 subtractLocalAverage(&data[0]);
137
138 return data;
139 }