annotate dsp/tonal/ChangeDetectionFunction.cpp @ 321:f1e6be2de9a5

A threshold (delta) is added in the peak picking parameters structure (PPickParams). It is used as an offset when computing the smoothed detection function. A constructor for the structure PPickParams is also added to set the parameters to 0 when a structure instance is created. Hence programmes using the peak picking parameter structure and which do not set the delta parameter (e.g. QM Vamp note onset detector) won't be affected by the modifications. Functions modified: - dsp/onsets/PeakPicking.cpp - dsp/onsets/PeakPicking.h - dsp/signalconditioning/DFProcess.cpp - dsp/signalconditioning/DFProcess.h
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Mon, 20 Jun 2011 19:01:48 +0100
parents d5014ab8b0e5
children cbe668c7d724
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
c@225 23
c@225 24 ChangeDetectionFunction::ChangeDetectionFunction(ChangeDFConfig config) :
c@225 25 m_dFilterSigma(0.0), m_iFilterWidth(0)
c@225 26 {
c@225 27 setFilterWidth(config.smoothingWidth);
c@225 28 }
c@225 29
c@225 30 ChangeDetectionFunction::~ChangeDetectionFunction()
c@225 31 {
c@225 32 }
c@225 33
c@225 34 void ChangeDetectionFunction::setFilterWidth(const int iWidth)
c@225 35 {
c@225 36 m_iFilterWidth = iWidth*2+1;
c@225 37
c@225 38 // it is assumed that the gaussian is 0 outside of +/- FWHM
c@225 39 // => filter width = 2*FWHM = 2*2.3548*sigma
c@225 40 m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548);
c@225 41 m_vaGaussian.resize(m_iFilterWidth);
c@225 42
c@225 43 double dScale = 1.0 / (m_dFilterSigma*sqrt(2*PI));
c@225 44
c@225 45 for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++)
c@225 46 {
c@225 47 double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) );
c@225 48 m_vaGaussian[x + (m_iFilterWidth-1)/2] = w;
c@225 49 }
c@225 50
c@225 51 #ifdef DEBUG_CHANGE_DETECTION_FUNCTION
c@275 52 std::cerr << "Filter sigma: " << m_dFilterSigma << std::endl;
c@275 53 std::cerr << "Filter width: " << m_iFilterWidth << std::endl;
c@225 54 #endif
c@225 55 }
c@225 56
c@225 57
c@225 58 ChangeDistance ChangeDetectionFunction::process(const TCSGram& rTCSGram)
c@225 59 {
c@225 60 ChangeDistance retVal;
c@225 61 retVal.resize(rTCSGram.getSize(), 0.0);
c@225 62
c@225 63 TCSGram smoothedTCSGram;
c@225 64
c@225 65 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++)
c@225 66 {
c@225 67 int iSkipLower = 0;
c@225 68
c@225 69 int iLowerPos = iPosition - (m_iFilterWidth-1)/2;
c@225 70 int iUpperPos = iPosition + (m_iFilterWidth-1)/2;
c@225 71
c@225 72 if (iLowerPos < 0)
c@225 73 {
c@225 74 iSkipLower = -iLowerPos;
c@225 75 iLowerPos = 0;
c@225 76 }
c@225 77
c@225 78 if (iUpperPos >= rTCSGram.getSize())
c@225 79 {
c@225 80 int iMaxIndex = rTCSGram.getSize() - 1;
c@225 81 iUpperPos = iMaxIndex;
c@225 82 }
c@225 83
c@225 84 TCSVector smoothedVector;
c@225 85
c@225 86 // for every bin of the vector, calculate the smoothed value
c@225 87 for (int iPC = 0; iPC < 6; iPC++)
c@225 88 {
c@225 89 size_t j = 0;
c@225 90 double dSmoothedValue = 0.0;
c@225 91 TCSVector rCV;
c@225 92
c@225 93 for (int i = iLowerPos; i <= iUpperPos; i++)
c@225 94 {
c@225 95 rTCSGram.getTCSVector(i, rCV);
c@225 96 dSmoothedValue += m_vaGaussian[iSkipLower + j++] * rCV[iPC];
c@225 97 }
c@225 98
c@225 99 smoothedVector[iPC] = dSmoothedValue;
c@225 100 }
c@225 101
c@225 102 smoothedTCSGram.addTCSVector(smoothedVector);
c@225 103 }
c@225 104
c@225 105 for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++)
c@225 106 {
c@225 107 /*
c@225 108 TODO: calculate a confidence measure for the current estimation
c@225 109 if the current estimate is not confident enough, look further into the future/the past
c@225 110 e.g., High frequency content, zero crossing rate, spectral flatness
c@225 111 */
c@225 112
c@225 113 TCSVector nextTCS;
c@225 114 TCSVector previousTCS;
c@225 115
c@225 116 int iWindow = 1;
c@225 117
c@225 118 // while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0)
c@225 119 {
c@225 120 smoothedTCSGram.getTCSVector(iPosition-iWindow, previousTCS);
c@225 121 // std::cout << previousTCS.magnitude() << std::endl;
c@225 122 iWindow++;
c@225 123 }
c@225 124
c@225 125 iWindow = 1;
c@225 126
c@225 127 // while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) )
c@225 128 {
c@225 129 smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS);
c@225 130 iWindow++;
c@225 131 }
c@225 132
c@225 133 double distance = 0.0;
c@225 134 // Euclidean distance
c@225 135 for (size_t j = 0; j < 6; j++)
c@225 136 {
c@225 137 distance += std::pow(nextTCS[j] - previousTCS[j], 2.0);
c@225 138 }
c@225 139
c@225 140 retVal[iPosition] = std::pow(distance, 0.5);
c@225 141 }
c@225 142
c@225 143 return retVal;
c@225 144 }