annotate Yin.cpp @ 20:1625cc4f4221

Added tag v1.0 for changeset b3acb3a6de12
author Chris Cannam
date Fri, 06 Dec 2013 16:19:26 +0000
parents 5945b8905d1f
children 70dd2b4e776b c0763eed48f0 83ee5e6d1577
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 "Yin.h"
matthiasm@0 15
matthiasm@0 16 #include "vamp-sdk/FFT.h"
matthiasm@0 17 #include "MeanFilter.h"
matthiasm@0 18 #include "YinUtil.h"
matthiasm@0 19
matthiasm@0 20 #include <vector>
matthiasm@0 21 #include <cstdlib>
matthiasm@0 22 #include <cstdio>
matthiasm@0 23 #include <cmath>
matthiasm@0 24 #include <complex>
matthiasm@0 25
matthiasm@0 26 using std::vector;
matthiasm@0 27
matthiasm@0 28 Yin::Yin(size_t frameSize, size_t inputSampleRate, double thresh) :
matthiasm@0 29 m_frameSize(frameSize),
matthiasm@0 30 m_inputSampleRate(inputSampleRate),
matthiasm@0 31 m_thresh(thresh),
matthiasm@0 32 m_threshDistr(2),
matthiasm@0 33 m_yinBufferSize(frameSize/2)
matthiasm@0 34 {
matthiasm@0 35 if (frameSize & (frameSize-1)) {
matthiasm@0 36 throw "N must be a power of two";
matthiasm@0 37 }
matthiasm@0 38 }
matthiasm@0 39
matthiasm@0 40 Yin::~Yin()
matthiasm@0 41 {
matthiasm@0 42 }
matthiasm@0 43
matthiasm@0 44 Yin::YinOutput
matthiasm@0 45 Yin::process(const double *in) const {
matthiasm@0 46
matthiasm@0 47 double* yinBuffer = new double[m_yinBufferSize];
matthiasm@0 48
matthiasm@0 49 // calculate aperiodicity function for all periods
matthiasm@0 50 YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@0 51 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
matthiasm@0 52
matthiasm@0 53 int tau = 0;
matthiasm@0 54 tau = YinUtil::absoluteThreshold(yinBuffer, m_yinBufferSize, m_thresh);
matthiasm@0 55
matthiasm@0 56 double interpolatedTau;
matthiasm@0 57 double aperiodicity;
matthiasm@0 58 double f0;
matthiasm@0 59
matthiasm@0 60 if (tau!=0)
matthiasm@0 61 {
matthiasm@0 62 interpolatedTau = YinUtil::parabolicInterpolation(yinBuffer, abs(tau), m_yinBufferSize);
matthiasm@0 63 f0 = m_inputSampleRate * (1.0 / interpolatedTau);
matthiasm@0 64 } else {
matthiasm@0 65 interpolatedTau = 0;
matthiasm@0 66 f0 = 0;
matthiasm@0 67 }
matthiasm@0 68 double rms = std::sqrt(YinUtil::sumSquare(in, 0, m_yinBufferSize)/m_yinBufferSize);
matthiasm@0 69 aperiodicity = yinBuffer[abs(tau)];
matthiasm@0 70 // std::cerr << aperiodicity << std::endl;
matthiasm@0 71 if (tau < 0) f0 = -f0;
matthiasm@0 72
matthiasm@0 73 Yin::YinOutput yo(f0, 1-aperiodicity, rms);
matthiasm@0 74 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
matthiasm@0 75 {
matthiasm@0 76 yo.salience.push_back(yinBuffer[iBuf] < 1 ? 1-yinBuffer[iBuf] : 0); // why are the values sometimes < 0 if I don't check?
matthiasm@0 77 }
matthiasm@0 78
matthiasm@0 79 delete [] yinBuffer;
matthiasm@0 80 return yo;
matthiasm@0 81 }
matthiasm@0 82
matthiasm@0 83 Yin::YinOutput
matthiasm@0 84 Yin::processProbabilisticYin(const double *in) const {
matthiasm@0 85
matthiasm@0 86 double* yinBuffer = new double[m_yinBufferSize];
matthiasm@0 87
matthiasm@0 88 // calculate aperiodicity function for all periods
matthiasm@0 89 YinUtil::fastDifference(in, yinBuffer, m_yinBufferSize);
matthiasm@0 90 YinUtil::cumulativeDifference(yinBuffer, m_yinBufferSize);
matthiasm@0 91
matthiasm@0 92 vector<double> peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
matthiasm@0 93
matthiasm@0 94 // calculate overall "probability" from peak probability
matthiasm@0 95 double probSum = 0;
matthiasm@0 96 for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
matthiasm@0 97 {
matthiasm@0 98 probSum += peakProbability[iBin];
matthiasm@0 99 }
matthiasm@0 100
matthiasm@0 101 Yin::YinOutput yo(0,0,0);
matthiasm@0 102 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
matthiasm@0 103 {
matthiasm@0 104 yo.salience.push_back(peakProbability[iBuf]);
matthiasm@0 105 if (peakProbability[iBuf] > 0)
matthiasm@0 106 {
matthiasm@0 107 double currentF0 =
matthiasm@0 108 m_inputSampleRate * (1.0 /
matthiasm@0 109 YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize));
matthiasm@0 110 yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf]));
matthiasm@0 111 }
matthiasm@0 112 }
matthiasm@0 113
matthiasm@0 114 // std::cerr << yo.freqProb.size() << std::endl;
matthiasm@0 115
matthiasm@0 116 delete [] yinBuffer;
matthiasm@0 117 return yo;
matthiasm@0 118 }
matthiasm@0 119
matthiasm@0 120
matthiasm@0 121 int
matthiasm@0 122 Yin::setThreshold(double parameter)
matthiasm@0 123 {
matthiasm@0 124 m_thresh = static_cast<float>(parameter);
matthiasm@0 125 return 0;
matthiasm@0 126 }
matthiasm@0 127
matthiasm@0 128 int
matthiasm@0 129 Yin::setThresholdDistr(float parameter)
matthiasm@0 130 {
matthiasm@0 131 m_threshDistr = static_cast<size_t>(parameter);
matthiasm@0 132 return 0;
matthiasm@0 133 }
matthiasm@0 134
matthiasm@0 135 int
matthiasm@0 136 Yin::setFrameSize(size_t parameter)
matthiasm@0 137 {
matthiasm@0 138 m_frameSize = parameter;
matthiasm@0 139 m_yinBufferSize = m_frameSize/2;
matthiasm@0 140 return 0;
matthiasm@0 141 }
matthiasm@0 142
matthiasm@0 143 // int
matthiasm@0 144 // Yin::setRemoveUnvoiced(bool parameter)
matthiasm@0 145 // {
matthiasm@0 146 // m_removeUnvoiced = parameter;
matthiasm@0 147 // return 0;
matthiasm@0 148 // }