1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
\r
4 pYIN - A fundamental frequency estimator for monophonic audio
\r
5 Centre for Digital Music, Queen Mary, University of London.
\r
7 This program is free software; you can redistribute it and/or
\r
8 modify it under the terms of the GNU General Public License as
\r
9 published by the Free Software Foundation; either version 2 of the
\r
10 License, or (at your option) any later version. See the file
\r
11 COPYING included with this distribution for more information.
\r
16 #include "vamp-sdk/FFT.h"
\r
17 #include "MeanFilter.h"
\r
18 #include "YinUtil.h"
\r
28 Yin::Yin(size_t frameSize, size_t inputSampleRate, double thresh, bool fast) :
\r
29 m_frameSize(frameSize),
\r
30 m_inputSampleRate(inputSampleRate),
\r
33 m_yinBufferSize(frameSize/2),
\r
36 if (frameSize & (frameSize-1)) {
\r
37 // throw "N must be a power of two";
\r
46 Yin::process(const double *in) const {
\r
48 double* yinBuffer = new double[m_yinBufferSize];
\r
50 // calculate aperiodicity function for all periods
\r
51 if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
\r
52 else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);
\r
54 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
\r
57 tau = YinUtil::absoluteThreshold(yinBuffer, m_yinBufferSize, m_thresh);
\r
59 double interpolatedTau;
\r
60 double aperiodicity;
\r
65 interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize);
\r
66 f0 = m_inputSampleRate * (1.0 / interpolatedTau);
\r
68 interpolatedTau = 0;
\r
71 double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
\r
72 aperiodicity = yinBuffer[abs(tau)];
\r
73 // std::cerr << aperiodicity << std::endl;
\r
74 if (tau < 0) f0 = -f0;
\r
76 Yin::YinOutput yo(f0, 1-aperiodicity, rms);
\r
77 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
\r
79 yo.salience.push_back(yinBuffer[iBuf] < 1 ? 1-yinBuffer[iBuf] : 0); // why are the values sometimes < 0 if I don't check?
\r
82 delete [] yinBuffer;
\r
87 Yin::processProbabilisticYin(const double *in) const {
\r
89 double* yinBuffer = new double[m_yinBufferSize];
\r
91 // calculate aperiodicity function for all periods
\r
92 if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
\r
93 else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);
\r
95 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
\r
97 vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
\r
99 // calculate overall "probability" from peak probability
\r
100 double probSum = 0;
\r
101 for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
\r
103 probSum += peakProbability[iBin];
\r
105 double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
\r
106 Yin::YinOutput yo(0,0,rms);
\r
107 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
\r
109 yo.salience.push_back(peakProbability[iBuf]);
\r
110 if (peakProbability[iBuf] > 0)
\r
113 m_inputSampleRate * (1.0 /
\r
114 YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize));
\r
115 yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf]));
\r
119 // std::cerr << yo.freqProb.size() << std::endl;
\r
121 delete [] yinBuffer;
\r
127 Yin::setThreshold(double parameter)
\r
129 m_thresh = static_cast<float>(parameter);
\r
134 Yin::setThresholdDistr(float parameter)
\r
136 m_threshDistr = static_cast<size_t>(parameter);
\r
141 Yin::setFrameSize(size_t parameter)
\r
143 m_frameSize = parameter;
\r
144 m_yinBufferSize = m_frameSize/2;
\r
149 Yin::setFast(bool parameter)
\r
151 m_fast = parameter;
\r