annotate Yin.cpp @ 164:a7d9c6142f8f tip

Added tag v1.2 for changeset 4a97f7638ffd
author Chris Cannam
date Thu, 06 Feb 2020 15:02:47 +0000
parents 7cbf40306c10
children
rev   line source
chris@52 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
chris@52 2
chris@52 3 /*
chris@52 4 pYIN - A fundamental frequency estimator for monophonic audio
chris@52 5 Centre for Digital Music, Queen Mary, University of London.
chris@52 6
chris@52 7 This program is free software; you can redistribute it and/or
chris@52 8 modify it under the terms of the GNU General Public License as
chris@52 9 published by the Free Software Foundation; either version 2 of the
chris@52 10 License, or (at your option) any later version. See the file
chris@52 11 COPYING included with this distribution for more information.
chris@52 12 */
chris@52 13
chris@52 14 #include "Yin.h"
chris@52 15
chris@52 16 #include "vamp-sdk/FFT.h"
chris@52 17 #include "MeanFilter.h"
chris@52 18 #include "YinUtil.h"
chris@52 19
chris@52 20 #include <vector>
chris@52 21 #include <cstdlib>
chris@52 22 #include <cstdio>
chris@52 23 #include <cmath>
chris@52 24 #include <complex>
chris@52 25
chris@52 26 using std::vector;
chris@52 27
matthiasm@117 28 Yin::Yin(size_t frameSize, size_t inputSampleRate, double thresh, bool fast) :
chris@52 29 m_frameSize(frameSize),
chris@52 30 m_inputSampleRate(inputSampleRate),
chris@52 31 m_thresh(thresh),
chris@52 32 m_threshDistr(2),
matthiasm@117 33 m_yinBufferSize(frameSize/2),
Chris@136 34 m_fast(fast),
Chris@136 35 m_yinUtil(new YinUtil(m_yinBufferSize))
chris@52 36 {
chris@52 37 if (frameSize & (frameSize-1)) {
chris@52 38 // throw "N must be a power of two";
chris@52 39 }
chris@52 40 }
chris@52 41
chris@52 42 Yin::~Yin()
chris@52 43 {
Chris@136 44 delete m_yinUtil;
chris@52 45 }
chris@52 46
chris@52 47 Yin::YinOutput
chris@52 48 Yin::process(const double *in) const {
chris@52 49
chris@52 50 double* yinBuffer = new double[m_yinBufferSize];
chris@52 51
chris@52 52 // calculate aperiodicity function for all periods
Chris@136 53 if (m_fast) m_yinUtil->fastDifference(in, yinBuffer);
Chris@136 54 else m_yinUtil->slowDifference(in, yinBuffer);
matthiasm@117 55
Chris@136 56 m_yinUtil->cumulativeDifference(yinBuffer);
chris@52 57
chris@52 58 int tau = 0;
Chris@136 59 tau = m_yinUtil->absoluteThreshold(yinBuffer, m_thresh);
chris@52 60
chris@52 61 double interpolatedTau;
chris@52 62 double aperiodicity;
chris@52 63 double f0;
chris@52 64
chris@52 65 if (tau!=0)
chris@52 66 {
Chris@136 67 interpolatedTau = m_yinUtil->parabolicInterpolation(yinBuffer, abs(tau));
chris@52 68 f0 = m_inputSampleRate * (1.0 / interpolatedTau);
chris@52 69 } else {
chris@52 70 interpolatedTau = 0;
chris@52 71 f0 = 0;
chris@52 72 }
Chris@136 73 double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
chris@52 74 aperiodicity = yinBuffer[abs(tau)];
chris@52 75 // std::cerr << aperiodicity << std::endl;
chris@52 76 if (tau < 0) f0 = -f0;
chris@52 77
chris@52 78 Yin::YinOutput yo(f0, 1-aperiodicity, rms);
chris@52 79 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
chris@52 80 {
chris@52 81 yo.salience.push_back(yinBuffer[iBuf] < 1 ? 1-yinBuffer[iBuf] : 0); // why are the values sometimes < 0 if I don't check?
chris@52 82 }
chris@52 83
chris@52 84 delete [] yinBuffer;
chris@52 85 return yo;
chris@52 86 }
chris@52 87
chris@52 88 Yin::YinOutput
chris@52 89 Yin::processProbabilisticYin(const double *in) const {
chris@52 90
chris@52 91 double* yinBuffer = new double[m_yinBufferSize];
chris@52 92
chris@52 93 // calculate aperiodicity function for all periods
Chris@136 94 if (m_fast) m_yinUtil->fastDifference(in, yinBuffer);
Chris@136 95 else m_yinUtil->slowDifference(in, yinBuffer);
matthiasm@117 96
Chris@136 97 m_yinUtil->cumulativeDifference(yinBuffer);
chris@52 98
Chris@136 99 vector<double> peakProbability = m_yinUtil->yinProb(yinBuffer, m_threshDistr);
chris@52 100
chris@52 101 // calculate overall "probability" from peak probability
chris@52 102 double probSum = 0;
chris@52 103 for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
chris@52 104 {
chris@52 105 probSum += peakProbability[iBin];
chris@52 106 }
Chris@136 107 double rms = std::sqrt(m_yinUtil->sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
matthiasm@103 108 Yin::YinOutput yo(0,0,rms);
chris@52 109 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
chris@52 110 {
chris@52 111 yo.salience.push_back(peakProbability[iBuf]);
chris@52 112 if (peakProbability[iBuf] > 0)
chris@52 113 {
chris@52 114 double currentF0 =
chris@52 115 m_inputSampleRate * (1.0 /
Chris@136 116 m_yinUtil->parabolicInterpolation(yinBuffer, iBuf));
chris@52 117 yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf]));
chris@52 118 }
chris@52 119 }
chris@52 120
chris@52 121 // std::cerr << yo.freqProb.size() << std::endl;
chris@52 122
chris@52 123 delete [] yinBuffer;
chris@52 124 return yo;
chris@52 125 }
chris@52 126
chris@52 127
chris@52 128 int
chris@52 129 Yin::setThreshold(double parameter)
chris@52 130 {
chris@52 131 m_thresh = static_cast<float>(parameter);
chris@52 132 return 0;
chris@52 133 }
chris@52 134
chris@52 135 int
chris@52 136 Yin::setThresholdDistr(float parameter)
chris@52 137 {
chris@52 138 m_threshDistr = static_cast<size_t>(parameter);
chris@52 139 return 0;
chris@52 140 }
chris@52 141
chris@52 142 int
chris@52 143 Yin::setFrameSize(size_t parameter)
chris@52 144 {
chris@52 145 m_frameSize = parameter;
chris@52 146 m_yinBufferSize = m_frameSize/2;
chris@52 147 return 0;
chris@52 148 }
chris@52 149
matthiasm@117 150 int
matthiasm@117 151 Yin::setFast(bool parameter)
matthiasm@117 152 {
matthiasm@117 153 m_fast = parameter;
matthiasm@117 154 return 0;
matthiasm@117 155 }