comparison dsp/tonal/ChangeDetectionFunction.cpp @ 225:49844bc8a895

* Queen Mary C++ DSP library
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 05 Apr 2006 17:35:59 +0000
parents
children 980b1a3b9cbe
comparison
equal deleted inserted replaced
-1:000000000000 225:49844bc8a895
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 QM DSP Library
5
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Martin Gasser.
8 All rights reserved.
9 */
10
11 #include "ChangeDetectionFunction.h"
12
13 #ifndef PI
14 #define PI (3.14159265358979232846)
15 #endif
16
17
18
19 ChangeDetectionFunction::ChangeDetectionFunction(ChangeDFConfig config) :
20 m_dFilterSigma(0.0), m_iFilterWidth(0)
21 {
22 setFilterWidth(config.smoothingWidth);
23 }
24
25 ChangeDetectionFunction::~ChangeDetectionFunction()
26 {
27 }
28
29 void ChangeDetectionFunction::setFilterWidth(const int iWidth)
30 {
31 m_iFilterWidth = iWidth*2+1;
32
33 // it is assumed that the gaussian is 0 outside of +/- FWHM
34 // => filter width = 2*FWHM = 2*2.3548*sigma
35 m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548);
36 m_vaGaussian.resize(m_iFilterWidth);
37
38 double dScale = 1.0 / (m_dFilterSigma*sqrt(2*PI));
39
40 for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++)
41 {
42 double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) );
43 m_vaGaussian[x + (m_iFilterWidth-1)/2] = w;
44 }
45
46 #ifdef DEBUG_CHANGE_DETECTION_FUNCTION
47 std::cout << "Filter sigma: " << m_dFilterSigma << std::endl;
48 std::cout << "Filter width: " << m_iFilterWidth << std::endl;
49 #endif
50 }
51
52
53 ChangeDistance ChangeDetectionFunction::process(const TCSGram& rTCSGram)
54 {
55 ChangeDistance retVal;
56 retVal.resize(rTCSGram.getSize(), 0.0);
57
58 TCSGram smoothedTCSGram;
59
60 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++)
61 {
62 int iSkipLower = 0;
63
64 int iLowerPos = iPosition - (m_iFilterWidth-1)/2;
65 int iUpperPos = iPosition + (m_iFilterWidth-1)/2;
66
67 if (iLowerPos < 0)
68 {
69 iSkipLower = -iLowerPos;
70 iLowerPos = 0;
71 }
72
73 if (iUpperPos >= rTCSGram.getSize())
74 {
75 int iMaxIndex = rTCSGram.getSize() - 1;
76 iUpperPos = iMaxIndex;
77 }
78
79 TCSVector smoothedVector;
80
81 // for every bin of the vector, calculate the smoothed value
82 for (int iPC = 0; iPC < 6; iPC++)
83 {
84 size_t j = 0;
85 double dSmoothedValue = 0.0;
86 TCSVector rCV;
87
88 for (int i = iLowerPos; i <= iUpperPos; i++)
89 {
90 rTCSGram.getTCSVector(i, rCV);
91 dSmoothedValue += m_vaGaussian[iSkipLower + j++] * rCV[iPC];
92 }
93
94 smoothedVector[iPC] = dSmoothedValue;
95 }
96
97 smoothedTCSGram.addTCSVector(smoothedVector);
98 }
99
100 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++)
101 {
102 /*
103 TODO: calculate a confidence measure for the current estimation
104 if the current estimate is not confident enough, look further into the future/the past
105 e.g., High frequency content, zero crossing rate, spectral flatness
106 */
107
108 TCSVector nextTCS;
109 TCSVector previousTCS;
110
111 int iWindow = 1;
112
113 // while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0)
114 {
115 smoothedTCSGram.getTCSVector(iPosition-iWindow, previousTCS);
116 // std::cout << previousTCS.magnitude() << std::endl;
117 iWindow++;
118 }
119
120 iWindow = 1;
121
122 // while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) )
123 {
124 smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS);
125 iWindow++;
126 }
127
128 double distance = 0.0;
129 // Euclidean distance
130 for (size_t j = 0; j < 6; j++)
131 {
132 distance += std::pow(nextTCS[j] - previousTCS[j], 2.0);
133 }
134
135 retVal[iPosition] = std::pow(distance, 0.5);
136 }
137
138 return retVal;
139 }