annotate dsp/tonal/ChangeDetectionFunction.cpp @ 209:ccd2019190bf msvc

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