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
|
matthiasm@0
|
22 const vector<double>
|
matthiasm@0
|
23 SparseHMM::calculateObsProb(const vector<pair<double, double> > data)
|
matthiasm@0
|
24 {
|
matthiasm@0
|
25 // dummy (virtual?) implementation to be overloaded
|
matthiasm@0
|
26 return(vector<double>());
|
matthiasm@0
|
27 }
|
matthiasm@0
|
28
|
matthiasm@0
|
29 const std::vector<int>
|
matthiasm@0
|
30 SparseHMM::decodeViterbi(std::vector<vector<double> > obsProb,
|
matthiasm@0
|
31 vector<double> *scale)
|
matthiasm@0
|
32 {
|
Chris@38
|
33 if (obsProb.size() < 1) {
|
Chris@38
|
34 return vector<int>();
|
Chris@38
|
35 }
|
Chris@38
|
36
|
matthiasm@0
|
37 size_t nState = init.size();
|
matthiasm@0
|
38 size_t nFrame = obsProb.size();
|
matthiasm@0
|
39
|
matthiasm@0
|
40 // check for consistency
|
matthiasm@0
|
41 size_t nTrans = transProb.size();
|
matthiasm@0
|
42
|
matthiasm@0
|
43 // declaring variables
|
matthiasm@0
|
44 std::vector<double> delta = std::vector<double>(nState);
|
matthiasm@0
|
45 std::vector<double> oldDelta = std::vector<double>(nState);
|
matthiasm@0
|
46 vector<vector<int> > psi; // "matrix" of remembered indices of the best transitions
|
matthiasm@0
|
47 vector<int> path = vector<int>(nFrame, nState-1); // the final output path (current assignment arbitrary, makes sense only for Chordino, where nChord-1 is the "no chord" label)
|
matthiasm@0
|
48
|
matthiasm@0
|
49 double deltasum = 0;
|
matthiasm@0
|
50
|
matthiasm@0
|
51 // initialise first frame
|
matthiasm@0
|
52 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
53 {
|
matthiasm@0
|
54 oldDelta[iState] = init[iState] * obsProb[0][iState];
|
matthiasm@0
|
55 // std::cerr << iState << " ----- " << init[iState] << std::endl;
|
matthiasm@0
|
56 deltasum += oldDelta[iState];
|
matthiasm@0
|
57 }
|
matthiasm@0
|
58
|
matthiasm@0
|
59 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
60 {
|
matthiasm@0
|
61 oldDelta[iState] /= deltasum; // normalise (scale)
|
matthiasm@0
|
62 // std::cerr << oldDelta[iState] << std::endl;
|
matthiasm@0
|
63 }
|
matthiasm@0
|
64
|
matthiasm@0
|
65 scale->push_back(1.0/deltasum);
|
matthiasm@0
|
66 psi.push_back(vector<int>(nState,0));
|
matthiasm@0
|
67
|
matthiasm@0
|
68 // rest of forward step
|
matthiasm@0
|
69 for (size_t iFrame = 1; iFrame < nFrame; ++iFrame)
|
matthiasm@0
|
70 {
|
matthiasm@0
|
71 deltasum = 0;
|
matthiasm@0
|
72 psi.push_back(vector<int>(nState,0));
|
matthiasm@0
|
73
|
matthiasm@0
|
74 // calculate best previous state for every current state
|
matthiasm@0
|
75 size_t fromState;
|
matthiasm@0
|
76 size_t toState;
|
matthiasm@0
|
77 double currentTransProb;
|
matthiasm@0
|
78 double currentValue;
|
matthiasm@0
|
79
|
matthiasm@0
|
80 // this is the "sparse" loop
|
matthiasm@0
|
81 for (size_t iTrans = 0; iTrans < nTrans; ++iTrans)
|
matthiasm@0
|
82 {
|
matthiasm@0
|
83 fromState = from[iTrans];
|
matthiasm@0
|
84 toState = to[iTrans];
|
matthiasm@0
|
85 currentTransProb = transProb[iTrans];
|
matthiasm@0
|
86
|
matthiasm@0
|
87 currentValue = oldDelta[fromState] * currentTransProb;
|
matthiasm@0
|
88 if (currentValue > delta[toState])
|
matthiasm@0
|
89 {
|
matthiasm@0
|
90 delta[toState] = currentValue; // will be multiplied by the right obs later!
|
matthiasm@0
|
91 psi[iFrame][toState] = fromState;
|
matthiasm@0
|
92 }
|
matthiasm@0
|
93 }
|
matthiasm@0
|
94
|
matthiasm@0
|
95 for (size_t jState = 0; jState < nState; ++jState)
|
matthiasm@0
|
96 {
|
matthiasm@0
|
97 delta[jState] *= obsProb[iFrame][jState];
|
matthiasm@0
|
98 deltasum += delta[jState];
|
matthiasm@0
|
99 }
|
matthiasm@0
|
100
|
matthiasm@0
|
101 if (deltasum > 0)
|
matthiasm@0
|
102 {
|
matthiasm@0
|
103 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
104 {
|
matthiasm@0
|
105 oldDelta[iState] = delta[iState] / deltasum; // normalise (scale)
|
matthiasm@0
|
106 delta[iState] = 0;
|
matthiasm@0
|
107 }
|
matthiasm@0
|
108 scale->push_back(1.0/deltasum);
|
matthiasm@0
|
109 } else
|
matthiasm@0
|
110 {
|
matthiasm@27
|
111 std::cerr << "WARNING: Viterbi has been fed some zero probabilities, at least they become zero at frame " << iFrame << " in combination with the model." << std::endl;
|
matthiasm@0
|
112 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
113 {
|
matthiasm@0
|
114 oldDelta[iState] = 1.0/nState;
|
matthiasm@0
|
115 delta[iState] = 0;
|
matthiasm@0
|
116 }
|
matthiasm@0
|
117 scale->push_back(1.0);
|
matthiasm@0
|
118 }
|
matthiasm@0
|
119 }
|
matthiasm@0
|
120
|
matthiasm@0
|
121 // initialise backward step
|
matthiasm@0
|
122 double bestValue = 0;
|
matthiasm@0
|
123 for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@0
|
124 {
|
matthiasm@0
|
125 double currentValue = oldDelta[iState];
|
matthiasm@0
|
126 if (currentValue > bestValue)
|
matthiasm@0
|
127 {
|
matthiasm@0
|
128 bestValue = currentValue;
|
matthiasm@0
|
129 path[nFrame-1] = iState;
|
matthiasm@0
|
130 }
|
matthiasm@0
|
131 }
|
matthiasm@0
|
132
|
matthiasm@0
|
133 // rest of backward step
|
matthiasm@0
|
134 for (int iFrame = nFrame-2; iFrame != -1; --iFrame)
|
matthiasm@0
|
135 {
|
matthiasm@0
|
136 path[iFrame] = psi[iFrame+1][path[iFrame+1]];
|
matthiasm@0
|
137 }
|
matthiasm@0
|
138
|
matthiasm@27
|
139 // for (size_t iState = 0; iState < nState; ++iState)
|
matthiasm@27
|
140 // {
|
matthiasm@27
|
141 // // std::cerr << psi[2][iState] << std::endl;
|
matthiasm@27
|
142 // }
|
matthiasm@0
|
143
|
matthiasm@0
|
144 return path;
|
matthiasm@0
|
145 }
|