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