Mercurial > hg > qm-dsp
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 } |