/// <summary> /// Get physical HMM and state distribution model mapping [Key = "HMM name", /// Value = "model names". First dimension is state, second dimension is stream]. /// </summary> /// <param name="mmfFileName">Binary HMM model file.</param> /// <returns>The model->state distribution mapping.</returns> public static Dictionary<string, string[,]> GetHmmAndStateMapping(string mmfFileName) { Helper.ThrowIfNull(mmfFileName); Dictionary<string, Collection<string>> hmmModels = new Dictionary<string, Collection<string>>(); int streamNumber = -1; using (HmmReader hr = new HmmReader(mmfFileName)) { bool isHmmPart = false; string hmmName = string.Empty; char macroType = ' '; while (hr.ReadNextMacro(out macroType)) { if (macroType.Equals('p') || macroType.Equals('s')) { string state = hr.ReadString(); if (isHmmPart) { Debug.Assert(hmmModels.ContainsKey(hmmName)); hmmModels[hmmName].Add(state); } else { // Don't skip reading the Gaussian distribution!! hr.ReadGaussian(); } } else if (macroType.Equals('t')) { if (!isHmmPart) { hr.ReadTransMatrix(); } } else if (macroType.Equals('h')) { hmmName = hr.ReadString(); if (!hmmModels.ContainsKey(hmmName)) { hmmModels.Add(hmmName, new Collection<string>()); } if (!isHmmPart) { isHmmPart = true; } } else if (macroType.Equals('o')) { HmmSymbol symbol = hr.ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.StreamInfo); short[] mmfStreamWidths = hr.ReadInt16Array(); streamNumber = mmfStreamWidths.Length; } else if (macroType == 'v') { hr.ReadVariance(); } } } Dictionary<string, string[,]> model2Streams = new Dictionary<string, string[,]>(); foreach (KeyValuePair<string, Collection<string>> pair in hmmModels) { Debug.Assert(pair.Value.Count % streamNumber == 0); int stateNumber = pair.Value.Count / streamNumber; string[,] streams = new string[stateNumber, streamNumber]; for (int i = 0; i < stateNumber; ++i) { for (int j = 0; j < streamNumber; ++j) { streams[i, j] = pair.Value[(i * streamNumber) + j]; } } model2Streams.Add(pair.Key, streams); } return model2Streams; }
/// <summary> /// Get Gaussians width information. /// </summary> /// <param name="hmr">Model reader.</param> /// <param name="streamIndexes">Stream indexes.</param> /// <returns>Stream Widths.</returns> public static int[] ReadStreamWidths(HmmReader hmr, int[] streamIndexes) { Helper.ThrowIfNull(hmr); Helper.ThrowIfNull(streamIndexes); HmmSymbol symbol = hmr.ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.StreamInfo); short[] mmfStreamWidths = hmr.ReadInt16Array(); Debug.Assert(streamIndexes.Length <= mmfStreamWidths.Length); int[] streamWidths = new int[streamIndexes.Length]; for (int i = 0; i < streamIndexes.Length; i++) { streamWidths[i] = mmfStreamWidths[streamIndexes[i] - 1]; // To 0 based index } if (hmr.ReadNextSymbol() == HmmSymbol.MSDINFO) { hmr.ReadInt16Array(); } return streamWidths; }