annotate YinUtil.cpp @ 164:a7d9c6142f8f tip

Added tag v1.2 for changeset 4a97f7638ffd
author Chris Cannam
date Thu, 06 Feb 2020 15:02:47 +0000
parents 81f025823a5c
children
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
Chris@140 22 YinUtil::YinUtil(int yinBufferSize) :
Chris@136 23 m_yinBufferSize(yinBufferSize),
Chris@136 24 m_fft(yinBufferSize * 2)
Chris@136 25 {
Chris@136 26 }
Chris@136 27
Chris@136 28 YinUtil::~YinUtil()
Chris@136 29 {
Chris@136 30 }
Chris@136 31
matthiasm@0 32 void
Chris@136 33 YinUtil::slowDifference(const double *in, double *yinBuffer)
matthiasm@60 34 {
matthiasm@60 35 yinBuffer[0] = 0;
matthiasm@60 36 double delta ;
matthiasm@60 37 int startPoint = 0;
matthiasm@60 38 int endPoint = 0;
Chris@137 39 for (int i = 1; i < int(m_yinBufferSize); ++i) {
matthiasm@60 40 yinBuffer[i] = 0;
Chris@136 41 startPoint = m_yinBufferSize/2 - i/2;
Chris@136 42 endPoint = startPoint + m_yinBufferSize;
matthiasm@60 43 for (int j = startPoint; j < endPoint; ++j) {
matthiasm@60 44 delta = in[i+j] - in[j];
matthiasm@60 45 yinBuffer[i] += delta * delta;
matthiasm@60 46 }
matthiasm@60 47 }
matthiasm@60 48 }
matthiasm@60 49
matthiasm@60 50 void
Chris@136 51 YinUtil::fastDifference(const double *in, double *yinBuffer)
matthiasm@0 52 {
matthiasm@0 53 // DECLARE AND INITIALISE
matthiasm@0 54 // initialisation of most of the arrays here was done in a separate function,
matthiasm@0 55 // with all the arrays as members of the class... moved them back here.
matthiasm@0 56
Chris@140 57 int frameSize = 2 * m_yinBufferSize;
Chris@140 58 int halfSize = m_yinBufferSize;
Chris@137 59
Chris@137 60 double *audioTransformedComplex = new double[frameSize + 2];
Chris@137 61 double *audioOutReal = new double[frameSize];
matthiasm@0 62 double *kernel = new double[frameSize];
Chris@137 63 double *kernelTransformedComplex = new double[frameSize + 2];
Chris@137 64 double *yinStyleACFComplex = new double[frameSize + 2];
Chris@136 65 double *powerTerms = new double[m_yinBufferSize];
matthiasm@0 66
matthiasm@0 67 // POWER TERM CALCULATION
matthiasm@0 68 // ... for the power terms in equation (7) in the Yin paper
matthiasm@0 69 powerTerms[0] = 0.0;
Chris@140 70 for (int j = 0; j < m_yinBufferSize; ++j) {
matthiasm@0 71 powerTerms[0] += in[j] * in[j];
matthiasm@0 72 }
matthiasm@0 73
matthiasm@0 74 // now iteratively calculate all others (saves a few multiplications)
Chris@140 75 for (int tau = 1; tau < m_yinBufferSize; ++tau) {
Chris@137 76 powerTerms[tau] = powerTerms[tau-1] -
Chris@137 77 in[tau-1] * in[tau-1] +
Chris@137 78 in[tau+m_yinBufferSize] * in[tau+m_yinBufferSize];
matthiasm@0 79 }
matthiasm@0 80
matthiasm@0 81 // YIN-STYLE AUTOCORRELATION via FFT
matthiasm@0 82 // 1. data
Chris@137 83 m_fft.forward(in, audioTransformedComplex);
matthiasm@0 84
matthiasm@0 85 // 2. half of the data, disguised as a convolution kernel
Chris@140 86 for (int j = 0; j < m_yinBufferSize; ++j) {
Chris@136 87 kernel[j] = in[m_yinBufferSize-1-j];
matthiasm@0 88 }
Chris@140 89 for (int j = m_yinBufferSize; j < frameSize; ++j) {
Chris@140 90 kernel[j] = 0.;
Chris@140 91 }
Chris@137 92 m_fft.forward(kernel, kernelTransformedComplex);
matthiasm@0 93
matthiasm@0 94 // 3. convolution via complex multiplication -- written into
Chris@140 95 for (int j = 0; j <= halfSize; ++j) {
Chris@137 96 yinStyleACFComplex[j*2] = // real
Chris@137 97 audioTransformedComplex[j*2] * kernelTransformedComplex[j*2] -
Chris@137 98 audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2+1];
Chris@137 99 yinStyleACFComplex[j*2+1] = // imaginary
Chris@137 100 audioTransformedComplex[j*2] * kernelTransformedComplex[j*2+1] +
Chris@137 101 audioTransformedComplex[j*2+1] * kernelTransformedComplex[j*2];
matthiasm@0 102 }
Chris@137 103
Chris@137 104 m_fft.inverse(yinStyleACFComplex, audioOutReal);
matthiasm@0 105
matthiasm@0 106 // CALCULATION OF difference function
matthiasm@0 107 // ... according to (7) in the Yin paper.
Chris@140 108 for (int j = 0; j < m_yinBufferSize; ++j) {
Chris@137 109 yinBuffer[j] = powerTerms[0] + powerTerms[j] - 2 *
Chris@137 110 audioOutReal[j+m_yinBufferSize-1];
matthiasm@0 111 }
Chris@137 112 delete [] audioTransformedComplex;
Chris@137 113 delete [] audioOutReal;
matthiasm@0 114 delete [] kernel;
Chris@137 115 delete [] kernelTransformedComplex;
Chris@137 116 delete [] yinStyleACFComplex;
matthiasm@0 117 delete [] powerTerms;
matthiasm@0 118 }
matthiasm@0 119
Chris@137 120
matthiasm@0 121 void
Chris@136 122 YinUtil::cumulativeDifference(double *yinBuffer)
matthiasm@0 123 {
Chris@140 124 int tau;
matthiasm@0 125
matthiasm@0 126 yinBuffer[0] = 1;
matthiasm@0 127
matthiasm@0 128 double runningSum = 0;
matthiasm@0 129
Chris@136 130 for (tau = 1; tau < m_yinBufferSize; ++tau) {
matthiasm@0 131 runningSum += yinBuffer[tau];
matthiasm@0 132 if (runningSum == 0)
matthiasm@0 133 {
matthiasm@0 134 yinBuffer[tau] = 1;
matthiasm@0 135 } else {
matthiasm@0 136 yinBuffer[tau] *= tau / runningSum;
matthiasm@0 137 }
matthiasm@0 138 }
matthiasm@0 139 }
matthiasm@0 140
matthiasm@0 141 int
Chris@140 142 YinUtil::absoluteThreshold(const double *yinBuffer, double thresh)
matthiasm@0 143 {
Chris@140 144 int tau;
Chris@140 145 int minTau = 0;
matthiasm@0 146 double minVal = 1000.;
matthiasm@0 147
matthiasm@0 148 // using Joren Six's "loop construct" from TarsosDSP
matthiasm@0 149 tau = 2;
Chris@136 150 while (tau < m_yinBufferSize)
matthiasm@0 151 {
matthiasm@0 152 if (yinBuffer[tau] < thresh)
matthiasm@0 153 {
Chris@136 154 while (tau+1 < m_yinBufferSize && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 155 {
matthiasm@0 156 ++tau;
matthiasm@0 157 }
matthiasm@0 158 return tau;
matthiasm@0 159 } else {
matthiasm@0 160 if (yinBuffer[tau] < minVal)
matthiasm@0 161 {
matthiasm@0 162 minVal = yinBuffer[tau];
matthiasm@0 163 minTau = tau;
matthiasm@0 164 }
matthiasm@0 165 }
matthiasm@0 166 ++tau;
matthiasm@0 167 }
matthiasm@0 168 if (minTau > 0)
matthiasm@0 169 {
matthiasm@0 170 return -minTau;
matthiasm@0 171 }
matthiasm@0 172 return 0;
matthiasm@0 173 }
matthiasm@0 174
Chris@154 175 #pragma GCC diagnostic ignored "-Wfloat-conversion"
Chris@154 176
Chris@61 177 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 178 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 179 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 180 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 181 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 182 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 183 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 184 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 185
matthiasm@31 186 std::vector<double>
Chris@140 187 YinUtil::yinProb(const double *yinBuffer, int prior, int minTau0, int maxTau0)
matthiasm@31 188 {
Chris@140 189 int minTau = 2;
Chris@140 190 int maxTau = m_yinBufferSize;
matthiasm@0 191
matthiasm@31 192 // adapt period range, if necessary
matthiasm@31 193 if (minTau0 > 0 && minTau0 < maxTau0) minTau = minTau0;
Chris@136 194 if (maxTau0 > 0 && maxTau0 < m_yinBufferSize && maxTau0 > minTau) maxTau = maxTau0;
matthiasm@31 195
matthiasm@0 196 double minWeight = 0.01;
Chris@140 197 int tau;
matthiasm@0 198 std::vector<float> thresholds;
matthiasm@0 199 std::vector<float> distribution;
Chris@136 200 std::vector<double> peakProb = std::vector<double>(m_yinBufferSize);
matthiasm@0 201
Chris@140 202 int nThreshold = 100;
matthiasm@0 203 int nThresholdInt = nThreshold;
matthiasm@0 204
matthiasm@0 205 for (int i = 0; i < nThresholdInt; ++i)
matthiasm@0 206 {
matthiasm@0 207 switch (prior) {
matthiasm@0 208 case 0:
matthiasm@0 209 distribution.push_back(uniformDist[i]);
matthiasm@0 210 break;
matthiasm@0 211 case 1:
matthiasm@0 212 distribution.push_back(betaDist1[i]);
matthiasm@0 213 break;
matthiasm@0 214 case 2:
matthiasm@0 215 distribution.push_back(betaDist2[i]);
matthiasm@0 216 break;
matthiasm@0 217 case 3:
matthiasm@0 218 distribution.push_back(betaDist3[i]);
matthiasm@0 219 break;
matthiasm@0 220 case 4:
matthiasm@0 221 distribution.push_back(betaDist4[i]);
matthiasm@0 222 break;
matthiasm@0 223 case 5:
matthiasm@0 224 distribution.push_back(single10[i]);
matthiasm@0 225 break;
matthiasm@0 226 case 6:
matthiasm@0 227 distribution.push_back(single15[i]);
matthiasm@0 228 break;
matthiasm@0 229 case 7:
matthiasm@0 230 distribution.push_back(single20[i]);
matthiasm@0 231 break;
matthiasm@0 232 default:
matthiasm@0 233 distribution.push_back(uniformDist[i]);
matthiasm@0 234 }
matthiasm@0 235 thresholds.push_back(0.01 + i*0.01);
matthiasm@0 236 }
matthiasm@0 237
matthiasm@0 238
matthiasm@0 239 int currThreshInd = nThreshold-1;
matthiasm@31 240 tau = minTau;
matthiasm@0 241
matthiasm@0 242 // double factor = 1.0 / (0.25 * (nThresholdInt+1) * (nThresholdInt + 1)); // factor to scale down triangular weight
Chris@140 243 int minInd = 0;
matthiasm@0 244 float minVal = 42.f;
matthiasm@46 245 // while (currThreshInd != -1 && tau < maxTau)
matthiasm@46 246 // {
matthiasm@46 247 // if (yinBuffer[tau] < thresholds[currThreshInd])
matthiasm@46 248 // {
matthiasm@46 249 // while (tau + 1 < maxTau && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@46 250 // {
matthiasm@46 251 // tau++;
matthiasm@46 252 // }
matthiasm@46 253 // // tau is now local minimum
matthiasm@46 254 // // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@46 255 // if (yinBuffer[tau] < minVal && tau > 2){
matthiasm@46 256 // minVal = yinBuffer[tau];
matthiasm@46 257 // minInd = tau;
matthiasm@46 258 // }
matthiasm@46 259 // peakProb[tau] += distribution[currThreshInd];
matthiasm@46 260 // currThreshInd--;
matthiasm@46 261 // } else {
matthiasm@46 262 // tau++;
matthiasm@46 263 // }
matthiasm@46 264 // }
matthiasm@46 265 // double nonPeakProb = 1;
Chris@140 266 // for (int i = minTau; i < maxTau; ++i)
matthiasm@46 267 // {
matthiasm@46 268 // nonPeakProb -= peakProb[i];
matthiasm@46 269 // }
matthiasm@46 270 //
matthiasm@46 271 // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@46 272 float sumProb = 0;
Chris@62 273 while (tau+1 < maxTau)
matthiasm@0 274 {
matthiasm@46 275 if (yinBuffer[tau] < thresholds[thresholds.size()-1] && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 276 {
matthiasm@31 277 while (tau + 1 < maxTau && yinBuffer[tau+1] < yinBuffer[tau])
matthiasm@0 278 {
matthiasm@0 279 tau++;
matthiasm@0 280 }
matthiasm@0 281 // tau is now local minimum
matthiasm@0 282 // std::cerr << tau << " " << currThreshInd << " "<< thresholds[currThreshInd] << " " << distribution[currThreshInd] << std::endl;
matthiasm@0 283 if (yinBuffer[tau] < minVal && tau > 2){
matthiasm@0 284 minVal = yinBuffer[tau];
matthiasm@0 285 minInd = tau;
matthiasm@0 286 }
matthiasm@46 287 currThreshInd = nThresholdInt-1;
Chris@137 288 while (currThreshInd > -1 && thresholds[currThreshInd] > yinBuffer[tau]) {
matthiasm@116 289 // std::cerr << distribution[currThreshInd] << std::endl;
matthiasm@116 290 peakProb[tau] += distribution[currThreshInd];
matthiasm@116 291 currThreshInd--;
matthiasm@116 292 }
matthiasm@116 293 // peakProb[tau] = 1 - yinBuffer[tau];
matthiasm@46 294 sumProb += peakProb[tau];
matthiasm@46 295 tau++;
matthiasm@0 296 } else {
matthiasm@0 297 tau++;
matthiasm@0 298 }
matthiasm@0 299 }
matthiasm@46 300
matthiasm@58 301 if (peakProb[minInd] > 1) {
matthiasm@58 302 std::cerr << "WARNING: yin has prob > 1 ??? I'm returning all zeros instead." << std::endl;
Chris@136 303 return(std::vector<double>(m_yinBufferSize));
matthiasm@58 304 }
matthiasm@58 305
matthiasm@0 306 double nonPeakProb = 1;
matthiasm@46 307 if (sumProb > 0) {
Chris@140 308 for (int i = minTau; i < maxTau; ++i)
matthiasm@46 309 {
matthiasm@46 310 peakProb[i] = peakProb[i] / sumProb * peakProb[minInd];
matthiasm@46 311 nonPeakProb -= peakProb[i];
matthiasm@46 312 }
matthiasm@0 313 }
matthiasm@0 314 if (minInd > 0)
matthiasm@0 315 {
matthiasm@0 316 // std::cerr << "min set " << minVal << " " << minInd << " " << nonPeakProb << std::endl;
matthiasm@0 317 peakProb[minInd] += nonPeakProb * minWeight;
matthiasm@0 318 }
matthiasm@0 319
matthiasm@0 320 return peakProb;
matthiasm@0 321 }
matthiasm@0 322
matthiasm@0 323 double
Chris@140 324 YinUtil::parabolicInterpolation(const double *yinBuffer, int tau)
matthiasm@0 325 {
matthiasm@0 326 // this is taken almost literally from Joren Six's Java implementation
Chris@136 327 if (tau == m_yinBufferSize) // not valid anyway.
matthiasm@0 328 {
matthiasm@0 329 return static_cast<double>(tau);
matthiasm@0 330 }
matthiasm@0 331
matthiasm@0 332 double betterTau = 0.0;
Chris@136 333 if (tau > 0 && tau < m_yinBufferSize-1) {
matthiasm@0 334 float s0, s1, s2;
matthiasm@46 335 s0 = yinBuffer[tau-1];
matthiasm@0 336 s1 = yinBuffer[tau];
matthiasm@46 337 s2 = yinBuffer[tau+1];
matthiasm@0 338
matthiasm@46 339 double adjustment = (s2 - s0) / (2 * (2 * s1 - s2 - s0));
matthiasm@0 340
matthiasm@46 341 if (abs(adjustment)>1) adjustment = 0;
matthiasm@46 342
matthiasm@46 343 betterTau = tau + adjustment;
matthiasm@46 344 } else {
matthiasm@118 345 // std::cerr << "WARNING: can't do interpolation at the edge (tau = " << tau << "), will return un-interpolated value.\n";
matthiasm@46 346 betterTau = tau;
matthiasm@0 347 }
matthiasm@0 348 return betterTau;
matthiasm@0 349 }
matthiasm@0 350
matthiasm@0 351 double
Chris@140 352 YinUtil::sumSquare(const double *in, int start, int end)
matthiasm@0 353 {
matthiasm@0 354 double out = 0;
Chris@140 355 for (int i = start; i < end; ++i)
matthiasm@0 356 {
matthiasm@0 357 out += in[i] * in[i];
matthiasm@0 358 }
matthiasm@0 359 return out;
matthiasm@0 360 }