/** * /// Attaches the given unit to the given tail, expanding the unit if necessary. If an identical unit is already * /// attached, then this path is folded into the existing path. * * /// @param parent the parent state * /// @param tail the place to attach the unit to * /// @param units the set of units * /// @param which the index into the set of units * /// @param leftContext the left context for the unit * /// @param rightContext the right context for the unit * /// @return the tail of the added unit (or null if the path was folded onto an already expanded path. */ private SentenceHMMState AttachUnit(PronunciationState parent, SentenceHMMState tail, Unit[] units, int which, UnitContext leftContext, UnitContext rightContext) { Unit[] lc = GetLC(leftContext, units, which); Unit[] rc = GetRC(units, which, rightContext); UnitContext actualRightContext = UnitContext.Get(rc); LeftRightContext context = LeftRightContext.Get(lc, rc); Unit cdUnit = _parent.UnitManager.GetUnit(units[which].Name, units[which].IsFiller, context); UnitState unitState = new ExtendedUnitState(parent, which, cdUnit); float logInsertionProbability; if (unitState.Unit.IsSilence) { logInsertionProbability = _parent.LogSilenceInsertionProbability; } else if (unitState.Unit.IsFiller) { logInsertionProbability = _parent._logFillerInsertionProbability; } else if (unitState.GetWhich() == 0) { logInsertionProbability = _parent._logWordInsertionProbability; } else { logInsertionProbability = _parent._logUnitInsertionProbability; } // check to see if this state already exists, if so // branch to it and we are done, otherwise, branch to // the new state and expand it. SentenceHMMState existingState = GetExistingState(unitState); if (existingState != null) { AttachState(tail, existingState, LogOne, logInsertionProbability); // T(" Folding " + existingState); return(null); } else { AttachState(tail, unitState, LogOne, logInsertionProbability); AddStateToCache(unitState); // T(" Attaching " + unitState); tail = ExpandUnit(unitState); // if we are attaching the last state of a word, then // we add it to the exitPoints table. the exit points // table is indexed by a ContextPair, consisting of // the exiting left context and the right context. if (unitState.IsLast()) { UnitContext nextLeftContext = GenerateNextLeftContext(leftContext, units[which]); ContextPair cp = ContextPair.Get(nextLeftContext, actualRightContext); // T(" Adding to exitPoints " + cp); AddExitPoint(cp, tail); } return(tail); } }
/** * /// Given a unit, search for the HMM associated with this unit by replacing all non-silence filler contexts with the * /// silence filler context * * /// @param unit the unit of interest * /// @return the associated hmm or null */ private SenoneHMM GetHMMInSilenceContext(Unit unit, HMMPosition position) { SenoneHMM hmm = null; var mgr = Loader.HMMManager; var context = unit.Context; if (context is LeftRightContext) { var lrContext = (LeftRightContext)context; var lc = lrContext.LeftContext; var rc = lrContext.RightContext; Unit[] nlc; Unit[] nrc; if (HasNonSilenceFiller(lc)) { nlc = ReplaceNonSilenceFillerWithSilence(lc); } else { nlc = lc; } if (HasNonSilenceFiller(rc)) { nrc = ReplaceNonSilenceFillerWithSilence(rc); } else { nrc = rc; } if (nlc != lc || nrc != rc) { Context newContext = LeftRightContext.Get(nlc, nrc); var newUnit = UnitManager.GetUnit(unit.Name, unit.IsFiller, newContext); hmm = (SenoneHMM)mgr.Get(position, newUnit); if (hmm == null) { hmm = GetHMMAtAnyPosition(newUnit); } } } return(hmm); }
/** * /// Loads the sphinx3 density file, a set of density arrays are created and * /// placed in the given pool. * /// * /// @param useCDUnits * /// if true, loads also the context dependent units * /// @param inputStream * /// the open input stream to use * /// @param path * /// the path to a density file * /// @throws FileNotFoundException * /// if a file cannot be found * /// @throws IOException * /// if an error occurs while loading the data */ protected void LoadHMMPool(Boolean useCDUnits, Stream inputStream, string path) { var est = new ExtendedStreamTokenizer(inputStream, '#', false); this.LogInfo("Loading HMM file from: " + path); est.ExpectString(ModelVersion); var numBase = est.GetInt("numBase"); est.ExpectString("n_base"); var numTri = est.GetInt("numTri"); est.ExpectString("n_tri"); var numStateMap = est.GetInt("numStateMap"); est.ExpectString("n_state_map"); var numTiedState = est.GetInt("numTiedState"); est.ExpectString("n_tied_state"); var numContextIndependentTiedState = est .GetInt("numContextIndependentTiedState"); est.ExpectString("n_tied_ci_state"); var numTiedTransitionMatrices = est.GetInt("numTiedTransitionMatrices"); est.ExpectString("n_tied_tmat"); var numStatePerHMM = numStateMap / (numTri + numBase); Debug.Assert(numTiedState == MixtureWeightsPool.StatesNum); Debug.Assert(numTiedTransitionMatrices == MatrixPool.Size); // Load the base phones for (var i = 0; i < numBase; i++) { var name = est.GetString(); var left = est.GetString(); var right = est.GetString(); var position = est.GetString(); var attribute = est.GetString(); var tmat = est.GetInt("tmat"); var stid = new int[numStatePerHMM - 1]; for (var j = 0; j < numStatePerHMM - 1; j++) { stid[j] = est.GetInt("j"); Debug.Assert(stid[j] >= 0 && stid[j] < numContextIndependentTiedState); } est.ExpectString("N"); Debug.Assert(left.Equals("-")); Debug.Assert(right.Equals("-")); Debug.Assert(position.Equals("-")); Debug.Assert(tmat < numTiedTransitionMatrices); var unit = _unitManager.GetUnit(name, attribute.Equals(Filler)); ContextIndependentUnits.Put(unit.Name, unit); //this.LogInfo("Loaded " + unit.ToString()); // The first filler if (unit.IsFiller && unit.Name.Equals(SilenceCiphone)) { unit = UnitManager.Silence; } var transitionMatrix = MatrixPool.Get(tmat); var ss = GetSenoneSequence(stid); IHMM hmm = new SenoneHMM(unit, ss, transitionMatrix, GetHMMPosition(position)); HmmManager.Put(hmm); } if (HmmManager.Get(HMMPosition.Undefined, UnitManager.Silence) == null) { throw new IOException("Could not find SIL unit in acoustic model"); } // Load the context dependent phones. If the useCDUnits // property is false, the CD phones will not be created, but // the values still need to be read in from the file. var lastUnitName = ""; Unit lastUnit = null; int[] lastStid = null; SenoneSequence lastSenoneSequence = null; for (var i = 0; i < numTri; i++) { var name = est.GetString(); var left = est.GetString(); var right = est.GetString(); var position = est.GetString(); var attribute = est.GetString(); var tmat = est.GetInt("tmat"); var stid = new int[numStatePerHMM - 1]; for (var j = 0; j < numStatePerHMM - 1; j++) { stid[j] = est.GetInt("j"); Debug.Assert(stid[j] >= numContextIndependentTiedState && stid[j] < numTiedState); } est.ExpectString("N"); Debug.Assert(!left.Equals("-")); Debug.Assert(!right.Equals("-")); Debug.Assert(!position.Equals("-")); Debug.Assert(attribute.Equals("n/a")); Debug.Assert(tmat < numTiedTransitionMatrices); if (useCDUnits) { Unit unit; var unitName = (name + ' ' + left + ' ' + right); if (unitName.Equals(lastUnitName)) { unit = lastUnit; } else { var leftContext = new Unit[1]; leftContext[0] = ContextIndependentUnits.Get(left); var rightContext = new Unit[1]; rightContext[0] = ContextIndependentUnits.Get(right); Context context = LeftRightContext.Get(leftContext, rightContext); unit = _unitManager.GetUnit(name, false, context); } lastUnitName = unitName; lastUnit = unit; //this.LogInfo("Loaded " + unit.ToString()); var transitionMatrix = MatrixPool.Get(tmat); var ss = lastSenoneSequence; if (ss == null || !SameSenoneSequence(stid, lastStid)) { ss = GetSenoneSequence(stid); } lastSenoneSequence = ss; lastStid = stid; IHMM hmm = new SenoneHMM(unit, ss, transitionMatrix, GetHMMPosition(position)); HmmManager.Put(hmm); } } est.Close(); }