Mercurial > hg > nnls-chroma
changeset 57:58a390dfba70 matthiasm-plugin
branch merge
author | matthiasm |
---|---|
date | Mon, 25 Oct 2010 21:52:11 +0900 |
parents | d1f2f69ba752 (current diff) 29ca32f50449 (diff) |
children | 01bc078f5f61 |
files | viterbi.o |
diffstat | 14 files changed, 274 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/Chordino.cpp Mon Oct 25 02:35:27 2010 +0900 +++ b/Chordino.cpp Mon Oct 25 21:52:11 2010 +0900 @@ -63,6 +63,104 @@ return "This plugin provides a number of features derived from a log-frequency amplitude spectrum of the DFT: some variants of the log-frequency spectrum, including a semitone spectrum derived from approximate transcription using the NNLS algorithm; based on this semitone spectrum, chroma features and a simple chord estimate."; } +Chordino::ParameterList +Chordino::getParameterDescriptors() const +{ + if (debug_on) cerr << "--> getParameterDescriptors" << endl; + ParameterList list; + + ParameterDescriptor d; + d.identifier = "useNNLS"; + d.name = "use approximate transcription (NNLS)"; + d.description = "Toggles approximate transcription (NNLS)."; + d.unit = ""; + d.minValue = 0.0; + d.maxValue = 1.0; + d.defaultValue = 1.0; + d.isQuantized = true; + d.quantizeStep = 1.0; + list.push_back(d); + + ParameterDescriptor d4; + d4.identifier = "useHMM"; + d4.name = "HMM (Viterbi decoding)"; + d4.description = "Turns on Viterbi decoding (when off, the simple chord estimator is used)."; + d4.unit = ""; + d4.minValue = 0.0; + d4.maxValue = 1.0; + d4.defaultValue = 1.0; + d4.isQuantized = true; + d4.quantizeStep = 1.0; + list.push_back(d4); + + ParameterDescriptor d0; + d0.identifier = "rollon"; + d0.name = "spectral roll-on"; + d0.description = "The bins below the spectral roll-on quantile will be set to 0."; + d0.unit = ""; + d0.minValue = 0; + d0.maxValue = 0.05; + d0.defaultValue = 0; + d0.isQuantized = true; + d0.quantizeStep = 0.005; + list.push_back(d0); + + ParameterDescriptor d1; + d1.identifier = "tuningmode"; + d1.name = "tuning mode"; + d1.description = "Tuning can be performed locally or on the whole extraction segment. Local tuning is only advisable when the tuning is likely to change over the audio, for example in podcasts, or in a cappella singing."; + d1.unit = ""; + d1.minValue = 0; + d1.maxValue = 1; + d1.defaultValue = 0; + d1.isQuantized = true; + d1.valueNames.push_back("global tuning"); + d1.valueNames.push_back("local tuning"); + d1.quantizeStep = 1.0; + list.push_back(d1); + + ParameterDescriptor d2; + d2.identifier = "whitening"; + d2.name = "spectral whitening"; + d2.description = "Spectral whitening: no whitening - 0; whitening - 1."; + d2.unit = ""; + d2.isQuantized = true; + d2.minValue = 0.0; + d2.maxValue = 1.0; + d2.defaultValue = 1.0; + d2.isQuantized = false; + list.push_back(d2); + + ParameterDescriptor d3; + d3.identifier = "s"; + d3.name = "spectral shape"; + d3.description = "Determines how individual notes in the note dictionary look: higher values mean more dominant higher harmonics."; + d3.unit = ""; + d3.minValue = 0.5; + d3.maxValue = 0.9; + d3.defaultValue = 0.7; + d3.isQuantized = false; + list.push_back(d3); + + // ParameterDescriptor d4; + // d4.identifier = "chromanormalize"; + // d4.name = "chroma normalization"; + // d4.description = "How shall the chroma vector be normalized?"; + // d4.unit = ""; + // d4.minValue = 0; + // d4.maxValue = 3; + // d4.defaultValue = 0; + // d4.isQuantized = true; + // d4.valueNames.push_back("none"); + // d4.valueNames.push_back("maximum norm"); + // d4.valueNames.push_back("L1 norm"); + // d4.valueNames.push_back("L2 norm"); + // d4.quantizeStep = 1.0; + // list.push_back(d4); + + return list; +} + Chordino::OutputList Chordino::getOutputDescriptors() const { @@ -367,7 +465,9 @@ for (int iBin = 12; iBin < 24; iBin++) { tempchordvalue += m_chorddict[24 * iChord + iBin] * chroma[iBin]; } - if (tempchordvalue < 0) tempchordvalue = 0; + if (iChord == nChord-1) tempchordvalue *= .7; + if (tempchordvalue < 0) tempchordvalue = 0.0; + tempchordvalue = pow(1.3,tempchordvalue); sumchordvalue+=tempchordvalue; currentChordSalience.push_back(tempchordvalue); } @@ -385,24 +485,36 @@ cerr << "done." << endl; - bool m_useHMM = true; // this will go into the chordino header file. - if (m_useHMM) { + // bool m_useHMM = true; // this will go into the chordino header file. + if (m_useHMM == 1.0) { cerr << "[Chordino Plugin] HMM Chord Estimation ... "; int oldchord = nChord-1; - double selftransprob = 0.9; + double selftransprob = 0.99; - vector<double> init = vector<double>(nChord,1.0/nChord); + // vector<double> init = vector<double>(nChord,1.0/nChord); + vector<double> init = vector<double>(nChord,0); init[nChord-1] = 1; + + double *delta; + delta = (double *)malloc(sizeof(double)*nFrame*nChord); + vector<vector<double> > trans; for (int iChord = 0; iChord < nChord; iChord++) { vector<double> temp = vector<double>(nChord,(1-selftransprob)/(nChord-1)); temp[iChord] = selftransprob; trans.push_back(temp); } - vector<int> chordpath = ViterbiPath(init,trans,chordogram); + vector<int> chordpath = ViterbiPath(init, trans, chordogram, delta); + + + Feature chord_feature; // chord estimate + chord_feature.hasTimestamp = true; + chord_feature.timestamp = timestamps[0]; + chord_feature.label = m_chordnames[chordpath[0]]; + fsOut[0].push_back(chord_feature); - for (int iFrame = 0; iFrame < chordpath.size(); ++iFrame) { + for (int iFrame = 1; iFrame < chordpath.size(); ++iFrame) { // cerr << chordpath[iFrame] << endl; - if (chordpath[iFrame] != oldchord) { + if (chordpath[iFrame] != oldchord ) { Feature chord_feature; // chord estimate chord_feature.hasTimestamp = true; chord_feature.timestamp = timestamps[iFrame]; @@ -410,6 +522,10 @@ fsOut[0].push_back(chord_feature); oldchord = chordpath[iFrame]; } + /* calculating simple chord change prob */ + for (int iChord = 0; iChord < nChord; iChord++) { + chordchange[iFrame-1] += delta[(iFrame-1)*nChord + iChord] * log(delta[(iFrame-1)*nChord + iChord]/delta[iFrame*nChord + iChord]); + } } // cerr << chordpath[0] << endl; @@ -502,7 +618,9 @@ for (unsigned iFrame = maxindex-1; iFrame < 2*halfwindowlength; ++iFrame) { scoreChordogram[iFrame+count][bestchordR]++; } - if (bestchordL != bestchordR) chordchange[maxindex+count] += (halfwindowlength - abs(maxindex-halfwindowlength)) * 2.0 / halfwindowlength; + if (bestchordL != bestchordR) { + chordchange[maxindex+count] += (halfwindowlength - abs(maxindex-halfwindowlength)) * 2.0 / halfwindowlength; + } count++; } // cerr << "******* agent finished *******" << endl; @@ -550,8 +668,7 @@ } // chordSequence[count] = maxChordIndex; // cerr << maxChordIndex << endl; - // cerr << chordchange[count] << endl; - // fsOut[9].push_back(currentChord); + // cerr << chordchange[count] << endl; if (oldChord != maxChord) { oldChord = maxChord; chord_feature.label = m_chordnames[maxChordIndex]; @@ -566,5 +683,17 @@ chord_feature.label = "N"; fsOut[0].push_back(chord_feature); cerr << "done." << endl; + + for (int iFrame = 0; iFrame < nFrame; iFrame++) { + Feature chordchange_feature; + chordchange_feature.hasTimestamp = true; + chordchange_feature.timestamp = timestamps[iFrame]; + chordchange_feature.values.push_back(chordchange[iFrame]); + fsOut[1].push_back(chordchange_feature); + } + + + + return fsOut; }
--- a/Chordino.h Mon Oct 25 02:35:27 2010 +0900 +++ b/Chordino.h Mon Oct 25 21:52:11 2010 +0900 @@ -34,6 +34,7 @@ string getName() const; string getDescription() const; + ParameterList getParameterDescriptors() const; OutputList getOutputDescriptors() const; FeatureSet process(const float *const *inputBuffers,
--- a/NNLSBase.cpp Mon Oct 25 02:35:27 2010 +0900 +++ b/NNLSBase.cpp Mon Oct 25 21:52:11 2010 +0900 @@ -55,7 +55,8 @@ m_doNormalizeChroma(0), m_rollon(0.0), m_s(0.7), - m_useNNLS(1) + m_useNNLS(1), + m_useHMM(1) { if (debug_on) cerr << "--> NNLSBase" << endl; @@ -166,7 +167,8 @@ d0.minValue = 0; d0.maxValue = 0.05; d0.defaultValue = 0; - d0.isQuantized = false; + d0.isQuantized = true; + d0.quantizeStep = 0.005; list.push_back(d0); ParameterDescriptor d1; @@ -258,6 +260,11 @@ if (identifier == "chromanormalize") { return m_doNormalizeChroma; } + + if (identifier == "useHMM") { + return m_useHMM; + } + return 0; } @@ -278,6 +285,10 @@ m_s = value; } + if (identifier == "useHMM") { + m_useHMM = value; + } + if (identifier == "tuningmode") { m_tuneLocal = (value > 0) ? true : false; // cerr << "m_tuneLocal :" << m_tuneLocal << endl;
--- a/NNLSBase.h Mon Oct 25 02:35:27 2010 +0900 +++ b/NNLSBase.h Mon Oct 25 21:52:11 2010 +0900 @@ -70,6 +70,7 @@ float m_preset; float m_s; float m_useNNLS; + float m_useHMM; vector<float> m_localTuning; vector<float> m_kernelValue; vector<int> m_kernelFftIndex;
--- a/README Mon Oct 25 02:35:27 2010 +0900 +++ b/README Mon Oct 25 21:52:11 2010 +0900 @@ -1,7 +1,7 @@ ## NNLS Chroma ## -System identifier – vamp:nnls-chroma:nnls_chroma -RDF URI – http://vamp-plugins.org/rdf/plugins/matthiasm#nnls_chroma (not yet available) +System identifier – vamp:nnls-chroma:nnls-chroma +RDF URI – http://vamp-plugins.org/rdf/plugins/nnls-chroma#nnls-chroma (not yet available) ### General Description ### @@ -14,6 +14,7 @@ ### Parameters ### The default settings (in brackets, below) are those used for Matthias Mauch's 2010 MIREX submissions. + * use approximate transcription (NNLS) (on or off; default: on): toggle between NNLS approximate transcription and linear spectral mapping. * spectral roll on (0.00 -- 0.05; default: 0.0): consider the cumulative energy spectrum (from low to high frequencies). All bins below the first bin whose cumulative energy exceeds [spectral roll on] x [total energy] will be set to 0. A value of 0 means that no bins will be changed. * tuning mode (global or local; default: global): local uses a local average for tuning, global uses ... exactly. @@ -23,4 +24,58 @@ ### Outputs ### -### References and Credits ### \ No newline at end of file +* Log-frequency Spectrum: a spectrum similar to the well-known constant Q spectrum, in which bins are linear in log-frequency. Three bins per semitone. +* Tuned Log-frequency Spectrum: has the same format as Log-frequency Spectrum, but has been processed by the following processes: tuning, subtraction of background spectrum, spectral whitening. +* Semitone Spectrum: a spectral representation with one bin per semitone. If NNLS is selected in the parameters, this is the note activation, otherwise just a linear mapping to semitones. +* Bass Chromagram: a 12-dimensional chromagram, restricted to the bass range. At each frame the Semitone Spectrum is multiplied by a bass pattern and then mapped to the 12 chroma bins. +* Chromagram: a 12-dimensional chromagram, restricted with mid-range emphasis. At each frame the Semitone Spectrum is multiplied by a mid-range pattern and then mapped to the 12 chroma bins. +* Chromagram and Bass Chromagram: a 24-dimensional chromagram, consisting of the both Bass Chromgram and Chromagram, see above. When normalisation is used, this representation will however be scaled differently, and hence be different from the individual chromagrams. + +## Chordino ## + +System identifier – vamp:nnls-chroma:chordino +RDF URI – http://vamp-plugins.org/rdf/plugins/nnls-chroma#chordino (not yet available) + +### General Description ### + +Chordino provides a simple chord transcription based on NNLS Chroma (described above). Chord profiles given by the user in the file "chord.dict" are used to calculate frame-wise chord similarities. Two simple (non-state-of-the-art!) algorithms are available that smooth these to provide a chord transcription: a simple chord change method, and a standard HMM/Viterbi approach. + +### Parameters ### + +The default settings (in brackets, below) are those used for Matthias Mauch's 2010 MIREX submissions. + +* use approximate transcription (NNLS) (on or off; default: on): toggle between NNLS approximate transcription and linear spectral mapping. +* HMM (Viterbi decoding) (on or off; default: on): uses HMM/Viterbi smoothing. Otherwise: heuristic chord change smoothing. +* spectral roll on (0.00 -- 0.05; default: 0.0): consider the cumulative energy spectrum (from low to high frequencies). All bins below the first bin whose cumulative energy exceeds [spectral roll on] x [total energy] will be set to 0. A value of 0 means that no bins will be changed. +* tuning mode (global or local; default: global): local uses a local average for tuning, global uses ... exactly. +* spectral whitening (0.0 -- 1.0; default: 1.0): determines how much the log-frequency spectrum is whitened. A value of 0.0 means no whitening. For values other than 0.0 the log-freq spectral bins are divided by [standard deviation of their neighbours]^[spectral whitening], where "^" means "to the power of". +* spectral shape (0.5 -- 0.9; default: 0.7): the shape of the notes in the NNLS dictionary. Their harmonic amplitude follows a geometrically decreasing pattern, in which the i-th harmonic has an amplitude of [spectral shape]^[i-1], where "^" means "to the power of". +* chroma normalisation (none, maximum norm, L1 norm, L2 norm; default: none): determines whether or how the chromagrams are normalised. If the setting is not 'none', then each chroma frame separately is divided by the chosen vector norm. Note that normalisation implies that the joint 24-dim. "Chroma and Bass Chromagram" output will be different from the individual 12-dim. "Chromagram" and "Bass Chromagram" outputs. + +### Outputs ### + +* Chord Estimate: estimated chord times and labels. +* Harmonic Change Value: an indication of the likelihood harmonic change. Depends on the chord dictionary. Calculation is different depending on whether the Viterbi algorithm is used for chord estimation, or the simple chord estimate. + +## Tuning ## + +System identifier – vamp:nnls-chroma:tuning +RDF URI – http://vamp-plugins.org/rdf/plugins/nnls-chroma#tuning (not yet available) + +### General Description ### + +The tuning plugin can estimate the local and global tuning of piece. The same tuning method is used for the NNLS Chroma and Chordino plugins. + +### Parameter ### + +* spectral roll on (0.00 -- 0.05; default: 0.0): consider the cumulative energy spectrum (from low to high frequencies). All bins below the first bin whose cumulative energy exceeds [spectral roll on] x [total energy] will be set to 0. A value of 0 means that no bins will be changed. + +### Outputs ### + +* Tuning: returns a single label at time 0 seconds containing the tuning information in Hz. +* Local Tuning: returns a tuning estimate at every analysis frame, an average of the (recent) previous frame-wise tuning estimates. + +## References and Credits ## + +Mauch, Matthias and Dixon, Simon: [*Approximate Note Transcription for the Improved Identification of Difficult Chords*](http://schall-und-mauch.de/artificialmusicality/?p=89), Proceedings of the 11th International Society for Music Information Retrieval Conference (ISMIR 2010), 2010. +
--- a/Tuning.cpp Mon Oct 25 02:35:27 2010 +0900 +++ b/Tuning.cpp Mon Oct 25 21:52:11 2010 +0900 @@ -41,6 +41,13 @@ if (debug_on) cerr << "--> ~Tuning" << endl; } +size_t +Tuning::getPreferredStepSize() const +{ + if (debug_on) cerr << "--> getPreferredStepSize" << endl; + return 2048*4; +} + string Tuning::getIdentifier() const { @@ -63,6 +70,28 @@ return "This plugin provides a number of features derived from a log-frequency amplitude spectrum of the DFT: some variants of the log-frequency spectrum, including a semitone spectrum derived from approximate transcription using the NNLS algorithm; based on this semitone spectrum, chroma features and a simple chord estimate."; } +Tuning::ParameterList +Tuning::getParameterDescriptors() const +{ + if (debug_on) cerr << "--> getParameterDescriptors" << endl; + ParameterList list; + + ParameterDescriptor d0; + d0.identifier = "rollon"; + d0.name = "spectral roll-on"; + d0.description = "The bins below the spectral roll-on quantile will be set to 0."; + d0.unit = ""; + d0.minValue = 0; + d0.maxValue = 0.05; + d0.defaultValue = 0; + d0.isQuantized = true; + d0.quantizeStep = 0.005; + list.push_back(d0); + + + return list; +} + Tuning::OutputList Tuning::getOutputDescriptors() const {
--- a/Tuning.h Mon Oct 25 02:35:27 2010 +0900 +++ b/Tuning.h Mon Oct 25 21:52:11 2010 +0900 @@ -33,7 +33,9 @@ string getIdentifier() const; string getName() const; string getDescription() const; - + size_t getPreferredStepSize() const; + + ParameterList getParameterDescriptors() const; OutputList getOutputDescriptors() const; FeatureSet process(const float *const *inputBuffers,
--- a/chord.dict Mon Oct 25 02:35:27 2010 +0900 +++ b/chord.dict Mon Oct 25 21:52:11 2010 +0900 @@ -16,13 +16,15 @@ 7=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0 maj7=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1 m7=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0 +m6=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,0,0 =0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0 =0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0 dim=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0 aug=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 =0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0 =0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0 -7=0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,0,1,0 +7=0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0 +# sus4=1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0 ### Rock'n'Roll # :1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0
--- a/chromamethods.cpp Mon Oct 25 02:35:27 2010 +0900 +++ b/chromamethods.cpp Mon Oct 25 21:52:11 2010 +0900 @@ -378,6 +378,7 @@ // // } + float exponent = 2.0; for (int iChord = 0; iChord < loadedChordDict.size()/24; iChord++) { float sum = 0; @@ -386,10 +387,10 @@ sum += loadedChordDict[24 * iChord + iST]; } for (int iST = 0; iST < 24; ++iST) { - loadedChordDict[24 * iChord + iST] -= sum/24; - stand += pow(loadedChordDict[24 * iChord + iST],2)/24; + // loadedChordDict[24 * iChord + iST] -= sum/24; + stand += pow(abs(loadedChordDict[24 * iChord + iST]),exponent)/24; } - stand = sqrt(stand); + stand = pow(stand,(float)1.0/exponent); for (int iST = 0; iST < 24; ++iST) { loadedChordDict[24 * iChord + iST] /= stand; }
--- a/nnls-chroma.cat Mon Oct 25 02:35:27 2010 +0900 +++ b/nnls-chroma.cat Mon Oct 25 21:52:11 2010 +0900 @@ -1,3 +1,3 @@ -vamp:nnls-chroma:chordino::Notes -vamp:nnls-chroma:nnls_chroma::Visualisation -vamp:nnls-chroma:tuning::Key and Tonality +vamp:nnls-chroma:chordino::Notes +vamp:nnls-chroma:nnls-chroma::Visualisation +vamp:nnls-chroma:tuning::Key and Tonality
--- a/viterbi.cpp Mon Oct 25 02:35:27 2010 +0900 +++ b/viterbi.cpp Mon Oct 25 21:52:11 2010 +0900 @@ -2,7 +2,7 @@ #include "viterbi.h" #include <iostream> -std::vector<int> ViterbiPath(std::vector<double> init, std::vector<vector<double> > trans, std::vector<vector<double> > obs) { +std::vector<int> ViterbiPath(std::vector<double> init, std::vector<vector<double> > trans, std::vector<vector<double> > obs, double *delta) { int nState = init.size(); int nFrame = obs.size(); @@ -12,8 +12,13 @@ if (trans[0].size() != nState || trans.size() != nState || obs[0].size() != nState) { cerr << "ERROR: matrix sizes inconsistent." << endl; } + + for (int iState = 0; iState < nState; ++iState) delta[iState] = init[iState]; + for (int iFrame = 1; iFrame < nFrame; ++iFrame) { + for (int iState = 0; iState < nState; ++iState) delta[iFrame*nState + iState]; + } - vector<vector<double> > delta; // "matrix" of conditional probabilities + // vector<vector<double> > delta; // "matrix" of conditional probabilities vector<vector<int> > psi; // "matrix" of remembered indices of the best transitions 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) vector<double> scale = vector<double>(nFrame, 0); // remembers by how much the vectors in delta are scaled. @@ -21,18 +26,18 @@ double deltasum = 0; /* initialise first frame */ - delta.push_back(init); + // delta.push_back(init); for (int iState = 0; iState < nState; ++iState) { - delta[0][iState] *= obs[0][iState]; - deltasum += delta[0][iState]; + delta[iState] *= obs[0][iState]; + deltasum += delta[iState]; } - for (int iState = 0; iState < nState; ++iState) delta[0][iState] /= deltasum; // normalise (scale) + for (int iState = 0; iState < nState; ++iState) delta[iState] /= deltasum; // normalise (scale) scale.push_back(1.0/deltasum); psi.push_back(vector<int>(nState,0)); /* rest of the forward step */ for (int iFrame = 1; iFrame < nFrame; ++iFrame) { - delta.push_back(vector<double>(nState,0)); + // delta.push_back(vector<double>(nState,0)); deltasum = 0; psi.push_back(vector<int>(nState,0)); /* every state wants to know which previous state suits him best */ @@ -41,7 +46,7 @@ double bestValue = 0; if (obs[iFrame][jState] > 0) { for (int iState = 0; iState < nState; ++iState) { - double currentValue = delta[iFrame-1][iState] * trans[iState][jState]; + double currentValue = delta[(iFrame-1) * nState + iState] * trans[iState][jState]; if (currentValue > bestValue) { bestValue = currentValue; bestState = iState; @@ -49,18 +54,18 @@ } } // cerr << bestState <<" ::: " << bestValue << endl ; - delta[iFrame][jState] = bestValue * obs[iFrame][jState]; - deltasum += delta[iFrame][jState]; + delta[iFrame * nState + jState] = bestValue * obs[iFrame][jState]; + deltasum += delta[iFrame * nState + jState]; psi[iFrame][jState] = bestState; } if (deltasum > 0) { for (int iState = 0; iState < nState; ++iState) { - delta[iFrame][iState] /= deltasum; // normalise (scale) + delta[iFrame * nState + iState] /= deltasum; // normalise (scale) } scale.push_back(1.0/deltasum); } else { for (int iState = 0; iState < nState; ++iState) { - delta[iFrame][iState] = 1.0/nState; + delta[iFrame * nState + iState] = 1.0/nState; } scale.push_back(1.0); } @@ -70,7 +75,7 @@ /* initialise backward step */ int bestValue = 0; for (int iState = 0; iState < nState; ++iState) { - double currentValue = delta[nFrame-1][iState]; + double currentValue = delta[(nFrame-1) * nState + iState]; if (currentValue > path[nFrame-1]) { bestValue = currentValue; path[nFrame-1] = iState;
--- a/viterbi.h Mon Oct 25 02:35:27 2010 +0900 +++ b/viterbi.h Mon Oct 25 21:52:11 2010 +0900 @@ -23,6 +23,6 @@ #include <string> using namespace std; -extern std::vector<int> ViterbiPath(std::vector<double> init, std::vector<vector<double> > trans, std::vector<vector<double> > obs); +extern std::vector<int> ViterbiPath(std::vector<double> init, std::vector<vector<double> > trans, std::vector<vector<double> > obs, double *delta); #endif \ No newline at end of file