annotate Yin.cpp @ 22:12cab92b7c26 interactive

added test track
author matthiasm
date Fri, 17 Jan 2014 12:10:33 +0000
parents 70dd2b4e776b
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 "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@21 84 Yin::processProbabilisticYin(const double *in, float minFreq, float maxFreq) 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@21 92 vector<double> peakProbability;
matthiasm@21 93 if ((minFreq < 0 && maxFreq < 0) || maxFreq < minFreq)
matthiasm@21 94 {
matthiasm@21 95 peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize);
matthiasm@21 96 } else {
matthiasm@21 97 if (minFreq < 0) minFreq = 0;
matthiasm@21 98 if (maxFreq < 0) maxFreq = m_inputSampleRate / 2;
matthiasm@21 99 int minTau = m_inputSampleRate / maxFreq;
matthiasm@21 100 int maxTau = m_inputSampleRate / minFreq;
matthiasm@21 101 peakProbability = YinUtil::yinProb(yinBuffer, m_threshDistr, m_yinBufferSize, minTau, maxTau);
matthiasm@21 102 }
matthiasm@21 103
matthiasm@0 104
matthiasm@0 105 // calculate overall "probability" from peak probability
matthiasm@0 106 double probSum = 0;
matthiasm@0 107 for (size_t iBin = 0; iBin < m_yinBufferSize; ++iBin)
matthiasm@0 108 {
matthiasm@0 109 probSum += peakProbability[iBin];
matthiasm@0 110 }
matthiasm@0 111
matthiasm@0 112 Yin::YinOutput yo(0,0,0);
matthiasm@0 113 for (size_t iBuf = 0; iBuf < m_yinBufferSize; ++iBuf)
matthiasm@0 114 {
matthiasm@0 115 yo.salience.push_back(peakProbability[iBuf]);
matthiasm@0 116 if (peakProbability[iBuf] > 0)
matthiasm@0 117 {
matthiasm@0 118 double currentF0 =
matthiasm@0 119 m_inputSampleRate * (1.0 /
matthiasm@0 120 YinUtil::parabolicInterpolation(yinBuffer, iBuf, m_yinBufferSize));
matthiasm@0 121 yo.freqProb.push_back(pair<double, double>(currentF0, peakProbability[iBuf]));
matthiasm@0 122 }
matthiasm@0 123 }
matthiasm@0 124
matthiasm@0 125 // std::cerr << yo.freqProb.size() << std::endl;
matthiasm@0 126
matthiasm@0 127 delete [] yinBuffer;
matthiasm@0 128 return yo;
matthiasm@0 129 }
matthiasm@0 130
matthiasm@0 131
matthiasm@0 132 int
matthiasm@0 133 Yin::setThreshold(double parameter)
matthiasm@0 134 {
matthiasm@0 135 m_thresh = static_cast<float>(parameter);
matthiasm@0 136 return 0;
matthiasm@0 137 }
matthiasm@0 138
matthiasm@0 139 int
matthiasm@0 140 Yin::setThresholdDistr(float parameter)
matthiasm@0 141 {
matthiasm@0 142 m_threshDistr = static_cast<size_t>(parameter);
matthiasm@0 143 return 0;
matthiasm@0 144 }
matthiasm@0 145
matthiasm@0 146 int
matthiasm@0 147 Yin::setFrameSize(size_t parameter)
matthiasm@0 148 {
matthiasm@0 149 m_frameSize = parameter;
matthiasm@0 150 m_yinBufferSize = m_frameSize/2;
matthiasm@0 151 return 0;
matthiasm@0 152 }
matthiasm@0 153
matthiasm@0 154 // int
matthiasm@0 155 // Yin::setRemoveUnvoiced(bool parameter)
matthiasm@0 156 // {
matthiasm@0 157 // m_removeUnvoiced = parameter;
matthiasm@0 158 // return 0;
matthiasm@0 159 // }