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