annotate SparseHMM.cpp @ 145:0432723faf03

Fix compiler warnings (no point in returning const type)
author Chris Cannam
date Fri, 24 Mar 2017 15:35:32 +0000
parents afcdcb64c8ab
children 8404827a4b02
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 "SparseHMM.h"
matthiasm@0 15 #include <vector>
matthiasm@0 16 #include <cstdio>
matthiasm@0 17 #include <iostream>
matthiasm@0 18
matthiasm@0 19 using std::vector;
matthiasm@0 20 using std::pair;
matthiasm@0 21
mail@132 22 SparseHMM::SparseHMM(int fixedLag) :
mail@132 23 m_fixedLag(fixedLag),
mail@130 24 m_nState(0),
mail@130 25 m_nTrans(0),
mail@130 26 m_init(0),
mail@130 27 m_from(0),
mail@130 28 m_to(0),
mail@130 29 m_transProb(0),
mail@130 30 m_scale(0),
mail@130 31 m_psi(0),
mail@130 32 m_delta(0),
mail@130 33 m_oldDelta(0)
mail@130 34 {
mail@130 35
mail@130 36 }
mail@130 37
Chris@145 38 vector<double>
Chris@138 39 SparseHMM::calculateObsProb(const vector<pair<double, double> > )
matthiasm@0 40 {
matthiasm@0 41 // dummy (virtual?) implementation to be overloaded
matthiasm@0 42 return(vector<double>());
matthiasm@0 43 }
matthiasm@0 44
mail@130 45 void
mail@130 46 SparseHMM::build()
mail@130 47 { }
mail@130 48
Chris@145 49 std::vector<int>
mail@130 50 SparseHMM::decodeViterbi(std::vector<vector<double> > obsProb)
matthiasm@0 51 {
Chris@142 52 int nFrame = obsProb.size();
mail@130 53 if (nFrame < 1) {
Chris@38 54 return vector<int>();
Chris@38 55 }
Chris@38 56
mail@130 57 initialise(obsProb[0]);
Chris@38 58
Chris@38 59 // rest of forward step
Chris@142 60 for (int iFrame = 1; iFrame < nFrame; ++iFrame)
Chris@38 61 {
mail@130 62 process(obsProb[iFrame]);
mail@130 63 }
Chris@38 64
mail@132 65 vector<int> path = track();
mail@130 66 return(path);
mail@130 67 }
mail@130 68
mail@131 69 void
mail@131 70 SparseHMM::reset()
mail@131 71 {
mail@131 72 m_scale.clear();
mail@131 73 m_psi.clear();
Chris@142 74 for (int i = 0; i < int(m_delta.size()); ++i) m_delta[i] = 0;
Chris@142 75 for (int i = 0; i < int(m_oldDelta.size()); ++i) m_oldDelta[i] = 0;
mail@131 76 }
mail@130 77
mail@130 78 void
mail@130 79 SparseHMM::initialise(vector<double> firstObs)
mail@130 80 {
mail@131 81 reset();
matthiasm@0 82
matthiasm@0 83 double deltasum = 0;
matthiasm@0 84
matthiasm@0 85 // initialise first frame
Chris@142 86 for (int iState = 0; iState < m_nState; ++iState)
matthiasm@0 87 {
mail@130 88 m_oldDelta[iState] = m_init[iState] * firstObs[iState];
mail@130 89 deltasum += m_oldDelta[iState];
matthiasm@0 90 }
matthiasm@0 91
Chris@142 92 for (int iState = 0; iState < m_nState; ++iState)
matthiasm@0 93 {
mail@130 94 m_oldDelta[iState] /= deltasum; // normalise (scale)
matthiasm@0 95 }
matthiasm@0 96
mail@130 97 m_scale.push_back(1.0/deltasum);
mail@130 98 m_psi.push_back(vector<int>(m_nState,0));
mail@130 99 }
matthiasm@0 100
mail@130 101 int
mail@130 102 SparseHMM::process(vector<double> newObs)
mail@130 103 {
mail@130 104 vector<int> tempPsi = vector<int>(m_nState,0);
mail@130 105
mail@130 106 // calculate best previous state for every current state
Chris@142 107 int fromState;
Chris@142 108 int toState;
mail@130 109 double currentTransProb;
mail@130 110 double currentValue;
mail@130 111
mail@130 112 // this is the "sparse" loop
Chris@142 113 for (int iTrans = 0; iTrans < m_nTrans; ++iTrans)
matthiasm@0 114 {
mail@130 115 fromState = m_from[iTrans];
mail@130 116 toState = m_to[iTrans];
mail@130 117 currentTransProb = m_transProb[iTrans];
matthiasm@0 118
mail@130 119 currentValue = m_oldDelta[fromState] * currentTransProb;
mail@130 120 if (currentValue > m_delta[toState])
matthiasm@0 121 {
mail@130 122 // will be multiplied by the right obs later!
mail@130 123 m_delta[toState] = currentValue;
mail@130 124 tempPsi[toState] = fromState;
matthiasm@0 125 }
matthiasm@0 126 }
mail@130 127 m_psi.push_back(tempPsi);
matthiasm@0 128
mail@130 129
mail@130 130 double deltasum = 0;
Chris@142 131 for (int jState = 0; jState < m_nState; ++jState)
mail@130 132 {
mail@130 133 m_delta[jState] *= newObs[jState];
mail@130 134 deltasum += m_delta[jState];
mail@130 135 }
mail@130 136
mail@130 137 if (deltasum > 0)
mail@130 138 {
Chris@142 139 for (int iState = 0; iState < m_nState; ++iState)
mail@130 140 {
mail@130 141 m_oldDelta[iState] = m_delta[iState] / deltasum;// normalise (scale)
mail@130 142 m_delta[iState] = 0;
mail@130 143 }
mail@130 144 m_scale.push_back(1.0/deltasum);
mail@130 145 } else
mail@130 146 {
mail@130 147 std::cerr << "WARNING: Viterbi has been fed some zero "
mail@130 148 "probabilities, at least they become zero "
mail@130 149 "in combination with the model." << std::endl;
Chris@142 150 for (int iState = 0; iState < m_nState; ++iState)
mail@130 151 {
mail@130 152 m_oldDelta[iState] = 1.0/m_nState;
mail@130 153 m_delta[iState] = 0;
mail@130 154 }
mail@130 155 m_scale.push_back(1.0);
mail@130 156 }
mail@132 157
Chris@142 158 if (m_fixedLag > 0 && int(m_psi.size()) > m_fixedLag)
mail@132 159 {
mail@132 160 m_psi.pop_front();
mail@132 161 m_scale.pop_front();
mail@132 162 }
mail@132 163
mail@132 164 // std::cerr << m_fixedLag << " " << m_psi.size() << std::endl;
mail@132 165
mail@130 166 return 0;
mail@130 167 }
mail@130 168
Chris@145 169 vector<int>
mail@132 170 SparseHMM::track()
mail@130 171 {
matthiasm@0 172 // initialise backward step
Chris@142 173 int nFrame = m_psi.size();
mail@130 174
mail@130 175 // The final output path (current assignment arbitrary, makes sense only for
mail@130 176 // Chordino, where nChord-1 is the "no chord" label)
mail@130 177 vector<int> path = vector<int>(nFrame, m_nState-1);
mail@130 178
matthiasm@0 179 double bestValue = 0;
Chris@142 180 for (int iState = 0; iState < m_nState; ++iState)
matthiasm@0 181 {
mail@130 182 double currentValue = m_oldDelta[iState];
matthiasm@0 183 if (currentValue > bestValue)
matthiasm@0 184 {
matthiasm@0 185 bestValue = currentValue;
matthiasm@0 186 path[nFrame-1] = iState;
matthiasm@0 187 }
matthiasm@0 188 }
matthiasm@0 189
mail@130 190 // Rest of backward step
matthiasm@0 191 for (int iFrame = nFrame-2; iFrame != -1; --iFrame)
matthiasm@0 192 {
mail@130 193 path[iFrame] = m_psi[iFrame+1][path[iFrame+1]];
matthiasm@0 194 }
mail@130 195
matthiasm@0 196 return path;
Chris@142 197 }