annotate YinUtil.cpp @ 137:109c3a2ad930 vamp-fft-revision

Make use of new Vamp FFT interface. This reduces the runtime of the regression test from 5.7 to 2.2 seconds on this machine, but it does need the right version of the SDK, which is currently only available in the vampipe branch.
author Chris Cannam
date Fri, 19 Aug 2016 13:26:40 +0100
parents 7cbf40306c10
children c2b426f4d841
rev   line source
Chris@9 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@9 2
Chris@9 3 /*
Chris@9 4 pYIN - A fundamental frequency estimator for monophonic audio
Chris@9 5 Centre for Digital Music, Queen Mary, University of London.
Chris@9 6
Chris@9 7 This program is free software; you can redistribute it and/or
Chris@9 8 modify it under the terms of the GNU General Public License as
Chris@9 9 published by the Free Software Foundation; either version 2 of the
Chris@9 10 License, or (at your option) any later version. See the file
Chris@9 11 COPYING included with this distribution for more information.
Chris@9 12 */
Chris@9 13
matthiasm@0 14 #include "YinUtil.h"
matthiasm@0 15
matthiasm@0 16 #include <vector>
matthiasm@0 17
matthiasm@0 18 #include <cstdio>
matthiasm@0 19 #include <cmath>
matthiasm@0 20 #include <algorithm>
matthiasm@0 21
matthiasm@0 22 #include <boost/math/distributions.hpp>
matthiasm@0 23
Chris@136 24 YinUtil::YinUtil(size_t yinBufferSize) :
Chris@136 25 m_yinBufferSize(yinBufferSize),
Chris@136 26 m_fft(yinBufferSize * 2)
Chris@136 27 {
Chris@136 28 }
Chris@136 29
Chris@136 30 YinUtil::~YinUtil()
Chris@136 31 {
Chris@136 32 }
Chris@136 33
matthiasm@0 34 void
Chris@136 35 YinUtil::slowDifference(const double *in, double *yinBuffer)
matthiasm@60 36 {
matthiasm@60 37 yinBuffer[0] = 0;
matthiasm@60 38 double delta ;
matthiasm@60 39 int startPoint = 0;
matthiasm@60 40 int endPoint = 0;
Chris@137 41 for (int i = 1; i < int(m_yinBufferSize); ++i) {
matthiasm@60 42 yinBuffer[i] = 0;
Chris@136 43 startPoint = m_yinBufferSize/2 - i/2;
Chris@136 44 endPoint = startPoint + m_yinBufferSize;
matthiasm@60 45 for (int j = startPoint; j < endPoint; ++j) {
matthiasm@60 46 delta = in[i+j] - in[j];
matthiasm@60 47 yinBuffer[i] += delta * delta;
matthiasm@60 48 }
matthiasm@60 49 }
matthiasm@60 50 }
matthiasm@60 51
matthiasm@60 52 void
Chris@136 53 YinUtil::fastDifference(const double *in, double *yinBuffer)
matthiasm@0 54 {
matthiasm@0 55 // DECLARE AND INITIALISE
matthiasm@0 56 // initialisation of most of the arrays here was done in a separate function,
matthiasm@0 57 // with all the arrays as members of the class... moved them back here.
matthiasm@0 58
Chris@136 59 size_t frameSize = 2 * m_yinBufferSize;
Chris@137 60 size_t halfSize = m_yinBufferSize;
Chris@137 61
Chris@137 62 double *audioTransformedComplex = new double[frameSize + 2];
Chris@137 63 double *audioOutReal = new double[frameSize];
matthiasm@0 64 double *kernel = new double[frameSize];
Chris@137 65 double *kernelTransformedComplex = new double[frameSize + 2];
Chris@137 66 double *yinStyleACFComplex = new double[frameSize + 2];
Chris@136 67 double *powerTerms = new double[m_yinBufferSize];
matthiasm@0 68
Chris@136 69 for (size_t j = 0; j < m_yinBufferSize; ++j)
matthiasm@0 70 {
matthiasm@58 71 yinBuffer[j] = 0.; // set to zero
matthiasm@58 72 powerTerms[j] = 0.; // set to zero
matthiasm@0 73 }
matthiasm@0 74
matthiasm@0 75 for (size_t j = 0; j < frameSize; ++j)
matthiasm@0 76 {
matthiasm@0 77 kernel[j] = 0.;
matthiasm@0 78 }
matthiasm@0 79
matthiasm@0 80 // POWER TERM CALCULATION
matthiasm@0 81 // ... for the power terms in equation (7) in the Yin paper
matthiasm@0 82 powerTerms[0] = 0.0;
Chris@136 83 for (size_t j = 0; j < m_yinBufferSize; ++j) {
matthiasm@0 84 powerTerms[0] += in[j] * in[j];
matthiasm@0 85 }
matthiasm@0 86
matthiasm@0 87 // now iteratively calculate all others (saves a few multiplications)
Chris@136 88 for (size_t tau = 1; tau < m_yinBufferSize; ++tau) {
Chris@137 89 powerTerms[tau] = powerTerms[tau-1] -
Chris@137 90 in[tau-1] * in[tau-1] +
Chris@137 91 in[tau+m_yinBufferSize] * in[tau+m_yinBufferSize];
matthiasm@0 92 }
matthiasm@0 93
matthiasm@0 94 // YIN-STYLE AUTOCORRELATION via FFT
matthiasm@0 95 // 1. data
Chris@137 96 m_fft.forward(in, audioTransformedComplex);
matthiasm@0 97
matthiasm@0 98 // 2. half of the data, disguised as a convolution kernel
Chris@136 99 for (size_t j = 0; j < m_yinBufferSize; ++j) {
Chris@136 100 kernel[j] = in[m_yinBufferSize-1-j];
matthiasm@0 101 }
Chris@137 102 m_fft.forward(kernel, kernelTransformedComplex);
matthiasm@0 103
matthiasm@0 104 // 3. convolution via complex multiplication -- written into
Chris@137 105 for (size_t j = 0; j <= halfSize; ++j) {
Chris@137 106 yinStyleACFComplex[j*2] = // real
Chris@137 107 audioTransformedComplex[j*2] * kernelTransformedComplex[j*2] -
Chris@137 108 audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2+1];
Chris@137 109 yinStyleACFComplex[j*2+1] = // imaginary
Chris@137 110 audioTransformedComplex[j*2] * kernelTransformedComplex[j*2+1] +
Chris@137 111 audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2];
matthiasm@0 112 }
Chris@137 113
Chris@137 114 m_fft.inverse(yinStyleACFComplex, audioOutReal);
matthiasm@0 115
matthiasm@0 116 // CALCULATION OF difference function
matthiasm@0 117 // ... according to (7) in the Yin paper.
Chris@136 118 for (size_t j = 0; j < m_yinBufferSize; ++j) {
Chris@137 119 yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 *
Chris@137 120 audioOutReal[j+m_yinBufferSize-1];
matthiasm@0 121 }
Chris@137 122 delete [] audioTransformedComplex;
Chris@137 123 delete [] audioOutReal;
matthiasm@0 124 delete [] kernel;
Chris@137 125 delete [] kernelTransformedComplex;
Chris@137 126 delete [] yinStyleACFComplex;
matthiasm@0 127 delete [] powerTerms;
matthiasm@0 128 }
matthiasm@0 129
Chris@137 130
matthiasm@0 131 void
Chris@136 132 YinUtil::cumulativeDifference(double *yinBuffer)
matthiasm@0 133 {
matthiasm@0 134 size_t tau;
matthiasm@0 135
matthiasm@0 136 yinBuffer[0] = 1;
matthiasm@0 137
matthiasm@0 138 double runningSum = 0;
matthiasm@0 139
Chris@136 140 for (tau = 1; tau < m_yinBufferSize; ++tau) {
matthiasm@0 141 runningSum += yinBuffer[tau];
matthiasm@0 142 if (runningSum == 0)
matthiasm@0 143 {
matthiasm@0 144 yinBuffer[tau] = 1;
matthiasm@0 145 } else {
matthiasm@0 146 yinBuffer[tau] *= tau / runningSum;
matthiasm@0 147 }
matthiasm@0 148 }
matthiasm@0 149 }
matthiasm@0 150
matthiasm@0 151 int
Chris@136 152 YinUtil::absoluteThreshold(const double *yinBuffer, const double thresh)
matthiasm@0 153 {
matthiasm@0 154 size_t tau;
matthiasm@0 155 size_t minTau = 0;
matthiasm@0 156 double minVal = 1000.;
matthiasm@0 157
matthiasm@0 158 // using Joren Six's "loop construct" from TarsosDSP
matthiasm@0 159 tau = 2;
Chris@136 160 while (tau < m_yinBufferSize)
matthiasm@0 161 {
matthiasm@0 162 if (yinBuffer[tau] < thresh)
matthiasm@0 163 {
Chris@136 164 while (tau+1 < m_yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 165 {
matthiasm@0 166 ++tau;
matthiasm@0 167 }
matthiasm@0 168 return tau;
matthiasm@0 169 } else {
matthiasm@0 170 if (yinBuffer[tau] < minVal)
matthiasm@0 171 {
matthiasm@0 172 minVal = yinBuffer[tau];
matthiasm@0 173 minTau = tau;
matthiasm@0 174 }
matthiasm@0 175 }
matthiasm@0 176 ++tau;
matthiasm@0 177 }
matthiasm@0 178 if (minTau > 0)
matthiasm@0 179 {
matthiasm@0 180 return -minTau;
matthiasm@0 181 }
matthiasm@0 182 return 0;
matthiasm@0 183 }
matthiasm@0 184
Chris@61 185 static float uniformDist[100] = {0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000,0.0100000};
Chris@61 186 static float betaDist1[100] = {0.028911,0.048656,0.061306,0.068539,0.071703,0.071877,0.069915,0.066489,0.062117,0.057199,0.052034,0.046844,0.041786,0.036971,0.032470,0.028323,0.024549,0.021153,0.018124,0.015446,0.013096,0.011048,0.009275,0.007750,0.006445,0.005336,0.004397,0.003606,0.002945,0.002394,0.001937,0.001560,0.001250,0.000998,0.000792,0.000626,0.000492,0.000385,0.000300,0.000232,0.000179,0.000137,0.000104,0.000079,0.000060,0.000045,0.000033,0.000024,0.000018,0.000013,0.000009,0.000007,0.000005,0.000003,0.000002,0.000002,0.000001,0.000001,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000};
Chris@61 187 static float betaDist2[100] = {0.012614,0.022715,0.030646,0.036712,0.041184,0.044301,0.046277,0.047298,0.047528,0.047110,0.046171,0.044817,0.043144,0.041231,0.039147,0.036950,0.034690,0.032406,0.030133,0.027898,0.025722,0.023624,0.021614,0.019704,0.017900,0.016205,0.014621,0.013148,0.011785,0.010530,0.009377,0.008324,0.007366,0.006497,0.005712,0.005005,0.004372,0.003806,0.003302,0.002855,0.002460,0.002112,0.001806,0.001539,0.001307,0.001105,0.000931,0.000781,0.000652,0.000542,0.000449,0.000370,0.000303,0.000247,0.000201,0.000162,0.000130,0.000104,0.000082,0.000065,0.000051,0.000039,0.000030,0.000023,0.000018,0.000013,0.000010,0.000007,0.000005,0.000004,0.000003,0.000002,0.000001,0.000001,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000};
Chris@61 188 static float betaDist3[100] = {0.006715,0.012509,0.017463,0.021655,0.025155,0.028031,0.030344,0.032151,0.033506,0.034458,0.035052,0.035331,0.035332,0.035092,0.034643,0.034015,0.033234,0.032327,0.031314,0.030217,0.029054,0.027841,0.026592,0.025322,0.024042,0.022761,0.021489,0.020234,0.019002,0.017799,0.016630,0.015499,0.014409,0.013362,0.012361,0.011407,0.010500,0.009641,0.008830,0.008067,0.007351,0.006681,0.006056,0.005475,0.004936,0.004437,0.003978,0.003555,0.003168,0.002814,0.002492,0.002199,0.001934,0.001695,0.001481,0.001288,0.001116,0.000963,0.000828,0.000708,0.000603,0.000511,0.000431,0.000361,0.000301,0.000250,0.000206,0.000168,0.000137,0.000110,0.000088,0.000070,0.000055,0.000043,0.000033,0.000025,0.000019,0.000014,0.000010,0.000007,0.000005,0.000004,0.000002,0.000002,0.000001,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000};
Chris@61 189 static float betaDist4[100] = {0.003996,0.007596,0.010824,0.013703,0.016255,0.018501,0.020460,0.022153,0.023597,0.024809,0.025807,0.026607,0.027223,0.027671,0.027963,0.028114,0.028135,0.028038,0.027834,0.027535,0.027149,0.026687,0.026157,0.025567,0.024926,0.024240,0.023517,0.022763,0.021983,0.021184,0.020371,0.019548,0.018719,0.017890,0.017062,0.016241,0.015428,0.014627,0.013839,0.013068,0.012315,0.011582,0.010870,0.010181,0.009515,0.008874,0.008258,0.007668,0.007103,0.006565,0.006053,0.005567,0.005107,0.004673,0.004264,0.003880,0.003521,0.003185,0.002872,0.002581,0.002312,0.002064,0.001835,0.001626,0.001434,0.001260,0.001102,0.000959,0.000830,0.000715,0.000612,0.000521,0.000440,0.000369,0.000308,0.000254,0.000208,0.000169,0.000136,0.000108,0.000084,0.000065,0.000050,0.000037,0.000027,0.000019,0.000014,0.000009,0.000006,0.000004,0.000002,0.000001,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000};
Chris@61 190 static float single10[100] = {0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,1.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000};
Chris@61 191 static float single15[100] = {0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,1.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000};
Chris@61 192 static float single20[100] = {0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,1.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000,0.00000};
Chris@61 193
matthiasm@31 194 std::vector<double>
Chris@136 195 YinUtil::yinProb(const double *yinBuffer, const size_t prior, const size_t minTau0, const size_t maxTau0)
matthiasm@31 196 {
matthiasm@31 197 size_t minTau = 2;
Chris@136 198 size_t maxTau = m_yinBufferSize;
matthiasm@0 199
matthiasm@31 200 // adapt period range, if necessary
matthiasm@31 201 if (minTau0 > 0 && minTau0 < maxTau0) minTau = minTau0;
Chris@136 202 if (maxTau0 > 0 && maxTau0 < m_yinBufferSize && maxTau0 > minTau) maxTau = maxTau0;
matthiasm@31 203
matthiasm@0 204 double minWeight = 0.01;
matthiasm@0 205 size_t tau;
matthiasm@0 206 std::vector<float> thresholds;
matthiasm@0 207 std::vector<float> distribution;
Chris@136 208 std::vector<double> peakProb = std::vector<double>(m_yinBufferSize);
matthiasm@0 209
matthiasm@0 210 size_t nThreshold = 100;
matthiasm@0 211 int nThresholdInt = nThreshold;
matthiasm@0 212
matthiasm@0 213 for (int i = 0; i < nThresholdInt; ++i)
matthiasm@0 214 {
matthiasm@0 215 switch (prior) {
matthiasm@0 216 case 0:
matthiasm@0 217 distribution.push_back(uniformDist[i]);
matthiasm@0 218 break;
matthiasm@0 219 case 1:
matthiasm@0 220 distribution.push_back(betaDist1[i]);
matthiasm@0 221 break;
matthiasm@0 222 case 2:
matthiasm@0 223 distribution.push_back(betaDist2[i]);
matthiasm@0 224 break;
matthiasm@0 225 case 3:
matthiasm@0 226 distribution.push_back(betaDist3[i]);
matthiasm@0 227 break;
matthiasm@0 228 case 4:
matthiasm@0 229 distribution.push_back(betaDist4[i]);
matthiasm@0 230 break;
matthiasm@0 231 case 5:
matthiasm@0 232 distribution.push_back(single10[i]);
matthiasm@0 233 break;
matthiasm@0 234 case 6:
matthiasm@0 235 distribution.push_back(single15[i]);
matthiasm@0 236 break;
matthiasm@0 237 case 7:
matthiasm@0 238 distribution.push_back(single20[i]);
matthiasm@0 239 break;
matthiasm@0 240 default:
matthiasm@0 241 distribution.push_back(uniformDist[i]);
matthiasm@0 242 }
matthiasm@0 243 thresholds.push_back(0.01 + i*0.01);
matthiasm@0 244 }
matthiasm@0 245
matthiasm@0 246
matthiasm@0 247 int currThreshInd = nThreshold-1;
matthiasm@31 248 tau = minTau;
matthiasm@0 249
matthiasm@0 250 // double factor = 1.0 / (0.25 * (nThresholdInt+1) * (nThresholdInt + 1)); // factor to scale down triangular weight
matthiasm@0 251 size_t minInd = 0;
matthiasm@0 252 float minVal = 42.f;
matthiasm@46 253 // while (currThreshInd != -1 && tau < maxTau)
matthiasm@46 254 // {
matthiasm@46 255 // if (yinBuffer[tau] < thresholds[currThreshInd])
matthiasm@46 256 // {
matthiasm@46 257 // while (tau + 1 < maxTau && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@46 258 // {
matthiasm@46 259 // tau++;
matthiasm@46 260 // }
matthiasm@46 261 // // tau is now local minimum
matthiasm@46 262 // // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@46 263 // if (yinBuffer[tau] < minVal && tau > 2){
matthiasm@46 264 // minVal = yinBuffer[tau];
matthiasm@46 265 // minInd = tau;
matthiasm@46 266 // }
matthiasm@46 267 // peakProb[tau] += distribution[currThreshInd];
matthiasm@46 268 // currThreshInd--;
matthiasm@46 269 // } else {
matthiasm@46 270 // tau++;
matthiasm@46 271 // }
matthiasm@46 272 // }
matthiasm@46 273 // double nonPeakProb = 1;
matthiasm@46 274 // for (size_t i = minTau; i < maxTau; ++i)
matthiasm@46 275 // {
matthiasm@46 276 // nonPeakProb -= peakProb[i];
matthiasm@46 277 // }
matthiasm@46 278 //
matthiasm@46 279 // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@46 280 float sumProb = 0;
Chris@62 281 while (tau+1 < maxTau)
matthiasm@0 282 {
matthiasm@46 283 if (yinBuffer[tau] < thresholds[thresholds.size()-1] && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 284 {
matthiasm@31 285 while (tau + 1 < maxTau && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 286 {
matthiasm@0 287 tau++;
matthiasm@0 288 }
matthiasm@0 289 // tau is now local minimum
matthiasm@0 290 // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@0 291 if (yinBuffer[tau] < minVal && tau > 2){
matthiasm@0 292 minVal = yinBuffer[tau];
matthiasm@0 293 minInd = tau;
matthiasm@0 294 }
matthiasm@46 295 currThreshInd = nThresholdInt-1;
Chris@137 296 while (currThreshInd > -1 && thresholds[currThreshInd] > yinBuffer[tau]) {
matthiasm@116 297 // std::cerr << distribution[currThreshInd] << std::endl;
matthiasm@116 298 peakProb[tau] += distribution[currThreshInd];
matthiasm@116 299 currThreshInd--;
matthiasm@116 300 }
matthiasm@116 301 // peakProb[tau] = 1 - yinBuffer[tau];
matthiasm@46 302 sumProb += peakProb[tau];
matthiasm@46 303 tau++;
matthiasm@0 304 } else {
matthiasm@0 305 tau++;
matthiasm@0 306 }
matthiasm@0 307 }
matthiasm@46 308
matthiasm@58 309 if (peakProb[minInd] > 1) {
matthiasm@58 310 std::cerr << "WARNING: yin has prob > 1 ??? I'm returning all zeros instead." << std::endl;
Chris@136 311 return(std::vector<double>(m_yinBufferSize));
matthiasm@58 312 }
matthiasm@58 313
matthiasm@0 314 double nonPeakProb = 1;
matthiasm@46 315 if (sumProb > 0) {
matthiasm@46 316 for (size_t i = minTau; i < maxTau; ++i)
matthiasm@46 317 {
matthiasm@46 318 peakProb[i] = peakProb[i] / sumProb * peakProb[minInd];
matthiasm@46 319 nonPeakProb -= peakProb[i];
matthiasm@46 320 }
matthiasm@0 321 }
matthiasm@0 322 if (minInd > 0)
matthiasm@0 323 {
matthiasm@0 324 // std::cerr << "min set " << minVal << " " << minInd << " " << nonPeakProb << std::endl;
matthiasm@0 325 peakProb[minInd] += nonPeakProb * minWeight;
matthiasm@0 326 }
matthiasm@0 327
matthiasm@0 328 return peakProb;
matthiasm@0 329 }
matthiasm@0 330
matthiasm@0 331 double
Chris@136 332 YinUtil::parabolicInterpolation(const double *yinBuffer, const size_t tau)
matthiasm@0 333 {
matthiasm@0 334 // this is taken almost literally from Joren Six's Java implementation
Chris@136 335 if (tau == m_yinBufferSize) // not valid anyway.
matthiasm@0 336 {
matthiasm@0 337 return static_cast<double>(tau);
matthiasm@0 338 }
matthiasm@0 339
matthiasm@0 340 double betterTau = 0.0;
Chris@136 341 if (tau > 0 && tau < m_yinBufferSize-1) {
matthiasm@0 342 float s0, s1, s2;
matthiasm@46 343 s0 = yinBuffer[tau-1];
matthiasm@0 344 s1 = yinBuffer[tau];
matthiasm@46 345 s2 = yinBuffer[tau+1];
matthiasm@0 346
matthiasm@46 347 double adjustment = (s2 - s0) / (2 * (2 * s1 - s2 - s0));
matthiasm@0 348
matthiasm@46 349 if (abs(adjustment)>1) adjustment = 0;
matthiasm@46 350
matthiasm@46 351 betterTau = tau + adjustment;
matthiasm@46 352 } else {
matthiasm@118 353 // std::cerr << "WARNING: can't do interpolation at the edge (tau = " << tau << "), will return un-interpolated value.\n";
matthiasm@46 354 betterTau = tau;
matthiasm@0 355 }
matthiasm@0 356 return betterTau;
matthiasm@0 357 }
matthiasm@0 358
matthiasm@0 359 double
matthiasm@0 360 YinUtil::sumSquare(const double *in, const size_t start, const size_t end)
matthiasm@0 361 {
matthiasm@0 362 double out = 0;
matthiasm@0 363 for (size_t i = start; i < end; ++i)
matthiasm@0 364 {
matthiasm@0 365 out += in[i] * in[i];
matthiasm@0 366 }
matthiasm@0 367 return out;
matthiasm@0 368 }