annotate Yin.cpp @ 126:292b75059949 v1.1

Update versions in n3 file as well
author Chris Cannam
date Tue, 21 Apr 2015 12:54:31 +0100
parents 1b75e5fd4b99
children 7cbf40306c10
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),
matthiasm@117 34 m_fast(fast)
chris@52 35 {
chris@52 36 if (frameSize & (frameSize-1)) {
chris@52 37 // throw "N must be a power of two";
chris@52 38 }
chris@52 39 }
chris@52 40
chris@52 41 Yin::~Yin()
chris@52 42 {
chris@52 43 }
chris@52 44
chris@52 45 Yin::YinOutput
chris@52 46 Yin::process(const double *in) const {
chris@52 47
chris@52 48 double* yinBuffer = new double[m_yinBufferSize];
chris@52 49
chris@52 50 // calculate aperiodicity function for all periods
matthiasm@117 51 if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@117 52 else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@117 53
chris@52 54 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
chris@52 55
chris@52 56 int tau = 0;
chris@52 57 tau = YinUtil::absoluteThreshold(yinBuffer, m_yinBufferSize, m_thresh);
chris@52 58
chris@52 59 double interpolatedTau;
chris@52 60 double aperiodicity;
chris@52 61 double f0;
chris@52 62
chris@52 63 if (tau!=0)
chris@52 64 {
chris@52 65 interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize);
chris@52 66 f0 = m_inputSampleRate * (1.0 / interpolatedTau);
chris@52 67 } else {
chris@52 68 interpolatedTau = 0;
chris@52 69 f0 = 0;
chris@52 70 }
chris@52 71 double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
chris@52 72 aperiodicity = yinBuffer[abs(tau)];
chris@52 73 // std::cerr << aperiodicity << std::endl;
chris@52 74 if (tau < 0) f0 = -f0;
chris@52 75
chris@52 76 Yin::YinOutput yo(f0, 1-aperiodicity, rms);
chris@52 77 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
chris@52 78 {
chris@52 79 yo.salience.push_back(yinBuffer[iBuf] < 1 ? 1-yinBuffer[iBuf] : 0); // why are the values sometimes < 0 if I don't check?
chris@52 80 }
chris@52 81
chris@52 82 delete [] yinBuffer;
chris@52 83 return yo;
chris@52 84 }
chris@52 85
chris@52 86 Yin::YinOutput
chris@52 87 Yin::processProbabilisticYin(const double *in) const {
chris@52 88
chris@52 89 double* yinBuffer = new double[m_yinBufferSize];
chris@52 90
chris@52 91 // calculate aperiodicity function for all periods
matthiasm@117 92 if (m_fast) YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@117 93 else YinUtil::slowDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@117 94
chris@52 95 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
chris@52 96
chris@52 97 vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
chris@52 98
chris@52 99 // calculate overall "probability" from peak probability
chris@52 100 double probSum = 0;
chris@52 101 for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
chris@52 102 {
chris@52 103 probSum += peakProbability[iBin];
chris@52 104 }
matthiasm@103 105 double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
matthiasm@103 106 Yin::YinOutput yo(0,0,rms);
chris@52 107 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
chris@52 108 {
chris@52 109 yo.salience.push_back(peakProbability[iBuf]);
chris@52 110 if (peakProbability[iBuf] > 0)
chris@52 111 {
chris@52 112 double currentF0 =
chris@52 113 m_inputSampleRate * (1.0 /
chris@52 114 YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize));
chris@52 115 yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf]));
chris@52 116 }
chris@52 117 }
chris@52 118
chris@52 119 // std::cerr << yo.freqProb.size() << std::endl;
chris@52 120
chris@52 121 delete [] yinBuffer;
chris@52 122 return yo;
chris@52 123 }
chris@52 124
chris@52 125
chris@52 126 int
chris@52 127 Yin::setThreshold(double parameter)
chris@52 128 {
chris@52 129 m_thresh = static_cast<float>(parameter);
chris@52 130 return 0;
chris@52 131 }
chris@52 132
chris@52 133 int
chris@52 134 Yin::setThresholdDistr(float parameter)
chris@52 135 {
chris@52 136 m_threshDistr = static_cast<size_t>(parameter);
chris@52 137 return 0;
chris@52 138 }
chris@52 139
chris@52 140 int
chris@52 141 Yin::setFrameSize(size_t parameter)
chris@52 142 {
chris@52 143 m_frameSize = parameter;
chris@52 144 m_yinBufferSize = m_frameSize/2;
chris@52 145 return 0;
chris@52 146 }
chris@52 147
matthiasm@117 148 int
matthiasm@117 149 Yin::setFast(bool parameter)
matthiasm@117 150 {
matthiasm@117 151 m_fast = parameter;
matthiasm@117 152 return 0;
matthiasm@117 153 }