Mercurial > hg > qm-dsp
comparison dsp/tonal/ChangeDetectionFunction.cpp @ 505:930b5b0f707d
Merge branch 'codestyle-and-tidy'
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Wed, 05 Jun 2019 12:55:15 +0100 |
parents | 7992d0923626 |
children |
comparison
equal
deleted
inserted
replaced
471:e3335cb213da | 505:930b5b0f707d |
---|---|
13 COPYING included with this distribution for more information. | 13 COPYING included with this distribution for more information. |
14 */ | 14 */ |
15 | 15 |
16 #include "ChangeDetectionFunction.h" | 16 #include "ChangeDetectionFunction.h" |
17 | 17 |
18 #ifndef PI | |
19 #define PI (3.14159265358979232846) | |
20 #endif | |
21 | |
22 | |
23 | |
24 ChangeDetectionFunction::ChangeDetectionFunction(ChangeDFConfig config) : | 18 ChangeDetectionFunction::ChangeDetectionFunction(ChangeDFConfig config) : |
25 m_dFilterSigma(0.0), m_iFilterWidth(0) | 19 m_dFilterSigma(0.0), m_iFilterWidth(0) |
26 { | 20 { |
27 setFilterWidth(config.smoothingWidth); | 21 setFilterWidth(config.smoothingWidth); |
28 } | 22 } |
29 | 23 |
30 ChangeDetectionFunction::~ChangeDetectionFunction() | 24 ChangeDetectionFunction::~ChangeDetectionFunction() |
31 { | 25 { |
32 } | 26 } |
33 | 27 |
34 void ChangeDetectionFunction::setFilterWidth(const int iWidth) | 28 void ChangeDetectionFunction::setFilterWidth(const int iWidth) |
35 { | 29 { |
36 m_iFilterWidth = iWidth*2+1; | 30 m_iFilterWidth = iWidth*2+1; |
37 | 31 |
38 // it is assumed that the gaussian is 0 outside of +/- FWHM | 32 // it is assumed that the gaussian is 0 outside of +/- FWHM |
39 // => filter width = 2*FWHM = 2*2.3548*sigma | 33 // => filter width = 2*FWHM = 2*2.3548*sigma |
40 m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548); | 34 m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548); |
41 m_vaGaussian.resize(m_iFilterWidth); | 35 m_vaGaussian.resize(m_iFilterWidth); |
42 | 36 |
43 double dScale = 1.0 / (m_dFilterSigma*sqrt(2*PI)); | 37 double dScale = 1.0 / (m_dFilterSigma*sqrt(2*M_PI)); |
44 | 38 |
45 for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++) | 39 for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++) { |
46 { | 40 double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) ); |
47 double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) ); | 41 m_vaGaussian[x + (m_iFilterWidth-1)/2] = w; |
48 m_vaGaussian[x + (m_iFilterWidth-1)/2] = w; | 42 } |
49 } | 43 |
50 | |
51 #ifdef DEBUG_CHANGE_DETECTION_FUNCTION | 44 #ifdef DEBUG_CHANGE_DETECTION_FUNCTION |
52 std::cerr << "Filter sigma: " << m_dFilterSigma << std::endl; | 45 std::cerr << "Filter sigma: " << m_dFilterSigma << std::endl; |
53 std::cerr << "Filter width: " << m_iFilterWidth << std::endl; | 46 std::cerr << "Filter width: " << m_iFilterWidth << std::endl; |
54 #endif | 47 #endif |
55 } | 48 } |
56 | 49 |
57 | 50 |
58 ChangeDistance ChangeDetectionFunction::process(const TCSGram& rTCSGram) | 51 ChangeDistance ChangeDetectionFunction::process(const TCSGram& rTCSGram) |
59 { | 52 { |
60 ChangeDistance retVal; | 53 ChangeDistance retVal; |
61 retVal.resize(rTCSGram.getSize(), 0.0); | 54 retVal.resize(rTCSGram.getSize(), 0.0); |
62 | 55 |
63 TCSGram smoothedTCSGram; | 56 TCSGram smoothedTCSGram; |
64 | 57 |
65 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) | 58 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) { |
66 { | 59 |
67 int iSkipLower = 0; | 60 int iSkipLower = 0; |
68 | 61 |
69 int iLowerPos = iPosition - (m_iFilterWidth-1)/2; | 62 int iLowerPos = iPosition - (m_iFilterWidth-1)/2; |
70 int iUpperPos = iPosition + (m_iFilterWidth-1)/2; | 63 int iUpperPos = iPosition + (m_iFilterWidth-1)/2; |
71 | 64 |
72 if (iLowerPos < 0) | 65 if (iLowerPos < 0) { |
73 { | 66 iSkipLower = -iLowerPos; |
74 iSkipLower = -iLowerPos; | 67 iLowerPos = 0; |
75 iLowerPos = 0; | 68 } |
76 } | 69 |
77 | 70 if (iUpperPos >= rTCSGram.getSize()) { |
78 if (iUpperPos >= rTCSGram.getSize()) | 71 int iMaxIndex = rTCSGram.getSize() - 1; |
79 { | 72 iUpperPos = iMaxIndex; |
80 int iMaxIndex = rTCSGram.getSize() - 1; | 73 } |
81 iUpperPos = iMaxIndex; | 74 |
82 } | 75 TCSVector smoothedVector; |
83 | |
84 TCSVector smoothedVector; | |
85 | 76 |
86 // for every bin of the vector, calculate the smoothed value | 77 // for every bin of the vector, calculate the smoothed value |
87 for (int iPC = 0; iPC < 6; iPC++) | 78 for (int iPC = 0; iPC < 6; iPC++) { |
88 { | |
89 size_t j = 0; | |
90 double dSmoothedValue = 0.0; | |
91 TCSVector rCV; | |
92 | |
93 for (int i = iLowerPos; i <= iUpperPos; i++) | |
94 { | |
95 rTCSGram.getTCSVector(i, rCV); | |
96 dSmoothedValue += m_vaGaussian[iSkipLower + j++] * rCV[iPC]; | |
97 } | |
98 | 79 |
99 smoothedVector[iPC] = dSmoothedValue; | 80 size_t j = 0; |
100 } | 81 double dSmoothedValue = 0.0; |
101 | 82 TCSVector rCV; |
102 smoothedTCSGram.addTCSVector(smoothedVector); | 83 |
103 } | 84 for (int i = iLowerPos; i <= iUpperPos; i++) { |
85 rTCSGram.getTCSVector(i, rCV); | |
86 dSmoothedValue += m_vaGaussian[iSkipLower + j++] * rCV[iPC]; | |
87 } | |
104 | 88 |
105 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) | 89 smoothedVector[iPC] = dSmoothedValue; |
106 { | 90 } |
107 /* | 91 |
108 TODO: calculate a confidence measure for the current estimation | 92 smoothedTCSGram.addTCSVector(smoothedVector); |
109 if the current estimate is not confident enough, look further into the future/the past | 93 } |
110 e.g., High frequency content, zero crossing rate, spectral flatness | |
111 */ | |
112 | |
113 TCSVector nextTCS; | |
114 TCSVector previousTCS; | |
115 | |
116 int iWindow = 1; | |
117 | 94 |
118 // while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0) | 95 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) { |
119 { | 96 |
120 smoothedTCSGram.getTCSVector(iPosition-iWindow, previousTCS); | 97 /* |
121 // std::cout << previousTCS.magnitude() << std::endl; | 98 TODO: calculate a confidence measure for the current estimation |
122 iWindow++; | 99 if the current estimate is not confident enough, look further into the future/the past |
123 } | 100 e.g., High frequency content, zero crossing rate, spectral flatness |
124 | 101 */ |
125 iWindow = 1; | 102 |
126 | 103 TCSVector nextTCS; |
127 // while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) ) | 104 TCSVector previousTCS; |
128 { | 105 |
129 smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS); | 106 int iWindow = 1; |
130 iWindow++; | |
131 } | |
132 | 107 |
133 double distance = 0.0; | 108 // while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0) |
134 // Euclidean distance | 109 { |
135 for (size_t j = 0; j < 6; j++) | 110 smoothedTCSGram.getTCSVector(iPosition-iWindow, previousTCS); |
136 { | 111 // std::cout << previousTCS.magnitude() << std::endl; |
137 distance += std::pow(nextTCS[j] - previousTCS[j], 2.0); | 112 iWindow++; |
138 } | 113 } |
139 | 114 |
140 retVal[iPosition] = std::pow(distance, 0.5); | 115 iWindow = 1; |
141 } | 116 |
117 // while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) ) | |
118 { | |
119 smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS); | |
120 iWindow++; | |
121 } | |
142 | 122 |
143 return retVal; | 123 double distance = 0.0; |
124 // Euclidean distance | |
125 for (size_t j = 0; j < 6; j++) { | |
126 distance += std::pow(nextTCS[j] - previousTCS[j], 2.0); | |
127 } | |
128 | |
129 retVal[iPosition] = std::pow(distance, 0.5); | |
130 } | |
131 | |
132 return retVal; | |
144 } | 133 } |