/** * /// Creates a UnitState. Gets the left and right contexts from the unit itself. * * /// @param parent the parent state * /// @param which the index of the given state * /// @param unit the unit associated with this state */ public UnitState(PronunciationState parent, int which, Unit unit) : base("U", parent, which) { this.Unit = unit; Unit[] units = parent.Pronunciation.Units; int length = units.Length; // If the last phone is SIL, then we should be using // a word-ending phone for the last phone. Decrementing // length will make the phone before SIL the last phone. if (units[length - 1] == UnitManager.Silence && length > 1) { length--; } if (length == 1) { _position = HMMPosition.Single; } else if (which == 0) { _position = HMMPosition.Begin; } else if (which == length - 1) { _position = HMMPosition.End; } }
/** * /// 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); } }
/** * /// Expand the pronunciation given the left context * * /// @param leftContext the left context * /// @param pronunciation the pronunciation to expand * /// @param which unique ID for this pronunciation */ // Each GState maintains a list of entry points. This list of // entry points is used when connecting up the end states of // one GState to the beginning states in another GState. The // entry points are tagged by a ContextPair which represents // the left context upon entering the state (the left context // of the initial units of the state), and the right context // of the previous states (corresponding to the starting // contexts for this state). // // When expanding a pronunciation, the following steps are // taken: // 1) Get the starting context for the pronunciation. // This is the set of units that correspond to the start // of the pronunciation. // // 2) Create a new PronunciationState for the // pronunciation. // // 3) Add the PronunciationState to the entry point table // (a hash table keyed by the ContextPair(LeftContext, // StartingContext). // // 4) Generate the set of context dependent units, using // the left and right context of the GState as necessary. // Note that there will be fan out at the end of the // pronunciation to allow for units with all of the // various right contexts. The point where the fan-out // occurs is the (length of the pronunciation - the max // right context size). // // 5) Attach each cd unit to the tree // // 6) Expand each cd unit into the set of HMM states // // 7) Attach the optional and looping back silence cd // unit // // 8) Collect the leaf states of the tree and add them to // the exitStates list. private void ExpandPronunciation(UnitContext leftContext, Pronunciation pronunciation, int which) { UnitContext startingContext = GetStartingContext(pronunciation); // Add the pronunciation state to the entry point list // (based upon its left and right context) string pname = "P(" + pronunciation.Word + '[' + leftContext + ',' + startingContext + "])-G" + GetNode().ID; PronunciationState ps = new PronunciationState(pname, pronunciation, which); _parent.T(" Expanding " + ps.Pronunciation + " for lc " + leftContext); ContextPair cp = ContextPair.Get(leftContext, startingContext); var epList = _entryPoints.Get(cp); if (epList == null) { throw new Error("No EP list for context pair " + cp); } else { epList.Add(ps); } Unit[] units = pronunciation.Units; int fanOutPoint = units.Length - GetRightContextSize(); if (fanOutPoint < 0) { fanOutPoint = 0; } SentenceHMMState tail = ps; for (int i = 0; tail != null && i < fanOutPoint; i++) { tail = AttachUnit(ps, tail, units, i, leftContext, UnitContext.Empty); } SentenceHMMState branchTail = tail; foreach (UnitContext finalRightContext in _rightContexts) { tail = branchTail; for (int i = fanOutPoint; tail != null && i < units.Length; i++) { tail = AttachUnit(ps, tail, units, i, leftContext, finalRightContext); } } }
/** * /// Creates a UnitState. Gets the left and right contexts from the unit itself. * * /// @param parent the parent state * /// @param which the index of the given state * /// @param unit the unit associated with this state */ public ExtendedUnitState(PronunciationState parent, int which, Unit unit) : base(parent, which, unit) { }