annotate MonoPitchHMM.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 7ef7f6e90966
children 080fe18f5ebf d71170f5ba76
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 "MonoPitchHMM.h"
matthiasm@0 15
matthiasm@0 16 #include <boost/math/distributions.hpp>
matthiasm@0 17
matthiasm@0 18 #include <cstdio>
matthiasm@0 19 #include <cmath>
matthiasm@0 20
matthiasm@0 21 using std::vector;
matthiasm@0 22 using std::pair;
matthiasm@0 23
matthiasm@0 24 MonoPitchHMM::MonoPitchHMM() :
matthiasm@102 25 m_minFreq(61.735),
matthiasm@24 26 m_nBPS(5),
matthiasm@0 27 m_nPitch(0),
matthiasm@0 28 m_transitionWidth(0),
matthiasm@0 29 m_selfTrans(0.99),
matthiasm@0 30 m_yinTrust(.5),
matthiasm@0 31 m_freqs(0)
matthiasm@0 32 {
matthiasm@0 33 m_transitionWidth = 5*(m_nBPS/2) + 1;
matthiasm@102 34 m_nPitch = 69 * m_nBPS;
matthiasm@25 35 m_freqs = vector<double>(2*m_nPitch);
matthiasm@0 36 for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch)
matthiasm@0 37 {
matthiasm@0 38 m_freqs[iPitch] = m_minFreq * std::pow(2, iPitch * 1.0 / (12 * m_nBPS));
matthiasm@0 39 m_freqs[iPitch+m_nPitch] = -m_freqs[iPitch];
matthiasm@0 40 }
matthiasm@0 41 build();
matthiasm@0 42 }
matthiasm@0 43
matthiasm@0 44 const vector<double>
matthiasm@0 45 MonoPitchHMM::calculateObsProb(const vector<pair<double, double> > pitchProb)
matthiasm@0 46 {
matthiasm@0 47 vector<double> out = vector<double>(2*m_nPitch+1);
matthiasm@0 48 double probYinPitched = 0;
matthiasm@0 49 // BIN THE PITCHES
matthiasm@0 50 for (size_t iPair = 0; iPair < pitchProb.size(); ++iPair)
matthiasm@0 51 {
matthiasm@0 52 double freq = 440. * std::pow(2, (pitchProb[iPair].first - 69)/12);
matthiasm@0 53 if (freq <= m_minFreq) continue;
matthiasm@0 54 double d = 0;
matthiasm@0 55 double oldd = 1000;
matthiasm@0 56 for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch)
matthiasm@0 57 {
matthiasm@0 58 d = std::abs(freq-m_freqs[iPitch]);
matthiasm@0 59 if (oldd < d && iPitch > 0)
matthiasm@0 60 {
matthiasm@0 61 // previous bin must have been the closest
matthiasm@0 62 out[iPitch-1] = pitchProb[iPair].second;
matthiasm@0 63 probYinPitched += out[iPitch-1];
matthiasm@0 64 break;
matthiasm@0 65 }
matthiasm@0 66 oldd = d;
matthiasm@0 67 }
matthiasm@0 68 }
matthiasm@0 69
matthiasm@0 70 double probReallyPitched = m_yinTrust * probYinPitched;
matthiasm@58 71 // std::cerr << probReallyPitched << " " << probYinPitched << std::endl;
matthiasm@58 72 // damn, I forget what this is all about...
matthiasm@0 73 for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch)
matthiasm@0 74 {
matthiasm@0 75 if (probYinPitched > 0) out[iPitch] *= (probReallyPitched/probYinPitched) ;
matthiasm@0 76 out[iPitch+m_nPitch] = (1 - probReallyPitched) / m_nPitch;
matthiasm@0 77 }
matthiasm@0 78 // out[2*m_nPitch] = m_yinTrust * (1 - probYinPitched);
matthiasm@0 79 return(out);
matthiasm@0 80 }
matthiasm@0 81
matthiasm@0 82 void
matthiasm@0 83 MonoPitchHMM::build()
matthiasm@0 84 {
matthiasm@0 85 // INITIAL VECTOR
matthiasm@25 86 init = vector<double>(2*m_nPitch, 1.0 / 2*m_nPitch);
matthiasm@0 87
matthiasm@0 88 // TRANSITIONS
matthiasm@0 89 for (size_t iPitch = 0; iPitch < m_nPitch; ++iPitch)
matthiasm@0 90 {
matthiasm@0 91 int theoreticalMinNextPitch = static_cast<int>(iPitch)-static_cast<int>(m_transitionWidth/2);
matthiasm@0 92 int minNextPitch = iPitch>m_transitionWidth/2 ? iPitch-m_transitionWidth/2 : 0;
matthiasm@0 93 int maxNextPitch = iPitch<m_nPitch-m_transitionWidth/2 ? iPitch+m_transitionWidth/2 : m_nPitch-1;
matthiasm@0 94
matthiasm@0 95 // WEIGHT VECTOR
matthiasm@0 96 double weightSum = 0;
matthiasm@0 97 vector<double> weights;
matthiasm@0 98 for (size_t i = minNextPitch; i <= maxNextPitch; ++i)
matthiasm@0 99 {
matthiasm@0 100 if (i <= iPitch)
matthiasm@0 101 {
matthiasm@0 102 weights.push_back(i-theoreticalMinNextPitch+1);
matthiasm@0 103 // weights.push_back(i-theoreticalMinNextPitch+1+m_transitionWidth/2);
matthiasm@0 104 } else {
matthiasm@0 105 weights.push_back(iPitch-theoreticalMinNextPitch+1-(i-iPitch));
matthiasm@0 106 // weights.push_back(iPitch-theoreticalMinNextPitch+1-(i-iPitch)+m_transitionWidth/2);
matthiasm@0 107 }
matthiasm@0 108 weightSum += weights[weights.size()-1];
matthiasm@0 109 }
matthiasm@0 110
matthiasm@0 111 // std::cerr << minNextPitch << " " << maxNextPitch << std::endl;
matthiasm@0 112 // TRANSITIONS TO CLOSE PITCH
matthiasm@0 113 for (size_t i = minNextPitch; i <= maxNextPitch; ++i)
matthiasm@0 114 {
matthiasm@0 115 from.push_back(iPitch);
matthiasm@0 116 to.push_back(i);
matthiasm@0 117 transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans);
matthiasm@0 118
matthiasm@0 119 from.push_back(iPitch);
matthiasm@0 120 to.push_back(i+m_nPitch);
matthiasm@0 121 transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans));
matthiasm@0 122
matthiasm@0 123 from.push_back(iPitch+m_nPitch);
matthiasm@0 124 to.push_back(i+m_nPitch);
matthiasm@0 125 transProb.push_back(weights[i-minNextPitch] / weightSum * m_selfTrans);
matthiasm@0 126 // transProb.push_back(weights[i-minNextPitch] / weightSum * 0.5);
matthiasm@0 127
matthiasm@0 128 from.push_back(iPitch+m_nPitch);
matthiasm@0 129 to.push_back(i);
matthiasm@0 130 transProb.push_back(weights[i-minNextPitch] / weightSum * (1-m_selfTrans));
matthiasm@0 131 // transProb.push_back(weights[i-minNextPitch] / weightSum * 0.5);
matthiasm@0 132 }
matthiasm@0 133
matthiasm@0 134 // TRANSITION TO UNVOICED
matthiasm@0 135 // from.push_back(iPitch+m_nPitch);
matthiasm@0 136 // to.push_back(2*m_nPitch);
matthiasm@0 137 // transProb.push_back(1-m_selfTrans);
matthiasm@0 138
matthiasm@0 139 // TRANSITION FROM UNVOICED TO PITCH
matthiasm@25 140 // from.push_back(2*m_nPitch);
matthiasm@25 141 // to.push_back(iPitch+m_nPitch);
matthiasm@25 142 // transProb.push_back(1.0/m_nPitch);
matthiasm@0 143 }
matthiasm@0 144 // UNVOICED SELFTRANSITION
matthiasm@0 145 // from.push_back(2*m_nPitch);
matthiasm@0 146 // to.push_back(2*m_nPitch);
matthiasm@0 147 // transProb.push_back(m_selfTrans);
matthiasm@0 148
matthiasm@0 149 // for (size_t i = 0; i < from.size(); ++i) {
matthiasm@0 150 // std::cerr << "P(["<< from[i] << " --> " << to[i] << "]) = " << transProb[i] << std::endl;
matthiasm@0 151 // }
matthiasm@0 152
Chris@9 153 }