annotate dsp/tonal/ChangeDetectionFunction.cpp @ 484:d48276a3ae24

Add emacs/vi indent directives
author Chris Cannam <cannam@all-day-breakfast.com>
date Fri, 31 May 2019 12:09:58 +0100
parents cbe668c7d724
children 7992d0923626
rev   line source
c@225 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@225 2
c@225 3 /*
c@225 4 QM DSP Library
c@225 5
c@225 6 Centre for Digital Music, Queen Mary, University of London.
c@225 7 This file copyright 2006 Martin Gasser.
c@309 8
c@309 9 This program is free software; you can redistribute it and/or
c@309 10 modify it under the terms of the GNU General Public License as
c@309 11 published by the Free Software Foundation; either version 2 of the
c@309 12 License, or (at your option) any later version. See the file
c@309 13 COPYING included with this distribution for more information.
c@225 14 */
c@225 15
c@225 16 #include "ChangeDetectionFunction.h"
c@225 17
c@225 18 #ifndef PI
c@225 19 #define PI (3.14159265358979232846)
c@225 20 #endif
c@225 21
c@225 22 ChangeDetectionFunction::ChangeDetectionFunction(ChangeDFConfig config) :
cannam@482 23 m_dFilterSigma(0.0), m_iFilterWidth(0)
c@225 24 {
cannam@482 25 setFilterWidth(config.smoothingWidth);
c@225 26 }
c@225 27
c@225 28 ChangeDetectionFunction::~ChangeDetectionFunction()
c@225 29 {
c@225 30 }
c@225 31
c@225 32 void ChangeDetectionFunction::setFilterWidth(const int iWidth)
c@225 33 {
cannam@482 34 m_iFilterWidth = iWidth*2+1;
cannam@482 35
cannam@482 36 // it is assumed that the gaussian is 0 outside of +/- FWHM
cannam@482 37 // => filter width = 2*FWHM = 2*2.3548*sigma
cannam@482 38 m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548);
cannam@482 39 m_vaGaussian.resize(m_iFilterWidth);
cannam@482 40
cannam@482 41 double dScale = 1.0 / (m_dFilterSigma*sqrt(2*PI));
cannam@482 42
cannam@482 43 for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++) {
cannam@482 44 double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) );
cannam@482 45 m_vaGaussian[x + (m_iFilterWidth-1)/2] = w;
cannam@482 46 }
cannam@482 47
c@225 48 #ifdef DEBUG_CHANGE_DETECTION_FUNCTION
cannam@482 49 std::cerr << "Filter sigma: " << m_dFilterSigma << std::endl;
cannam@482 50 std::cerr << "Filter width: " << m_iFilterWidth << std::endl;
c@225 51 #endif
c@225 52 }
c@225 53
c@225 54
c@225 55 ChangeDistance ChangeDetectionFunction::process(const TCSGram& rTCSGram)
c@225 56 {
cannam@482 57 ChangeDistance retVal;
cannam@482 58 retVal.resize(rTCSGram.getSize(), 0.0);
cannam@482 59
cannam@482 60 TCSGram smoothedTCSGram;
c@225 61
cannam@482 62 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) {
cannam@482 63
cannam@482 64 int iSkipLower = 0;
cannam@482 65
cannam@482 66 int iLowerPos = iPosition - (m_iFilterWidth-1)/2;
cannam@482 67 int iUpperPos = iPosition + (m_iFilterWidth-1)/2;
cannam@482 68
cannam@482 69 if (iLowerPos < 0) {
cannam@482 70 iSkipLower = -iLowerPos;
cannam@482 71 iLowerPos = 0;
cannam@482 72 }
cannam@482 73
cannam@482 74 if (iUpperPos >= rTCSGram.getSize()) {
cannam@482 75 int iMaxIndex = rTCSGram.getSize() - 1;
cannam@482 76 iUpperPos = iMaxIndex;
cannam@482 77 }
cannam@482 78
cannam@482 79 TCSVector smoothedVector;
c@225 80
cannam@482 81 // for every bin of the vector, calculate the smoothed value
cannam@482 82 for (int iPC = 0; iPC < 6; iPC++) {
c@225 83
cannam@482 84 size_t j = 0;
cannam@482 85 double dSmoothedValue = 0.0;
cannam@482 86 TCSVector rCV;
cannam@482 87
cannam@482 88 for (int i = iLowerPos; i <= iUpperPos; i++) {
cannam@482 89 rTCSGram.getTCSVector(i, rCV);
cannam@482 90 dSmoothedValue += m_vaGaussian[iSkipLower + j++] * rCV[iPC];
cannam@482 91 }
c@225 92
cannam@482 93 smoothedVector[iPC] = dSmoothedValue;
cannam@482 94 }
cannam@482 95
cannam@482 96 smoothedTCSGram.addTCSVector(smoothedVector);
cannam@482 97 }
c@225 98
cannam@482 99 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++) {
cannam@482 100
cannam@482 101 /*
cannam@482 102 TODO: calculate a confidence measure for the current estimation
cannam@482 103 if the current estimate is not confident enough, look further into the future/the past
cannam@482 104 e.g., High frequency content, zero crossing rate, spectral flatness
cannam@482 105 */
cannam@482 106
cannam@482 107 TCSVector nextTCS;
cannam@482 108 TCSVector previousTCS;
cannam@482 109
cannam@482 110 int iWindow = 1;
c@225 111
cannam@482 112 // while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0)
cannam@482 113 {
cannam@482 114 smoothedTCSGram.getTCSVector(iPosition-iWindow, previousTCS);
cannam@482 115 // std::cout << previousTCS.magnitude() << std::endl;
cannam@482 116 iWindow++;
cannam@482 117 }
cannam@482 118
cannam@482 119 iWindow = 1;
cannam@482 120
cannam@482 121 // while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) )
cannam@482 122 {
cannam@482 123 smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS);
cannam@482 124 iWindow++;
cannam@482 125 }
c@225 126
cannam@482 127 double distance = 0.0;
cannam@482 128 // Euclidean distance
cannam@482 129 for (size_t j = 0; j < 6; j++) {
cannam@482 130 distance += std::pow(nextTCS[j] - previousTCS[j], 2.0);
cannam@482 131 }
cannam@482 132
cannam@482 133 retVal[iPosition] = std::pow(distance, 0.5);
cannam@482 134 }
cannam@482 135
cannam@482 136 return retVal;
c@225 137 }