/// <summary> /// Loads the unit index and candidate data section from binary reader. /// </summary> /// <param name="reader">The given binary reader.</param> private void LoadCandidates(BinaryReader reader) { _waveCandidates.Clear(); _namedUnitIndexId.Clear(); reader.BaseStream.Seek(UnitIndexOffset, SeekOrigin.Begin); List<UnitIndexInfo> unitIndexInfos = new List<UnitIndexInfo>(); for (int i = 0; i < UnitIndexCount; ++i) { UnitIndexInfo unitIndexInfo = new UnitIndexInfo(); unitIndexInfo.Load(reader); unitIndexInfos.Add(unitIndexInfo); } int invalidUnit = 1; for (int i = 0; i < unitIndexInfos.Count; ++i) { if (unitIndexInfos[i].Offset != UnitIndexInfo.InvalidOffset) { reader.BaseStream.Seek(unitIndexInfos[i].Offset, SeekOrigin.Begin); _waveCandidates.Add(i, new IdKeyedWaveCandidateInfos()); string name = _stringPool.GetString((int)unitIndexInfos[i].UnitNameOffset); _namedUnitIndexId.Add(name, i); _unitNameStringPoolOffsets.Add(name, unitIndexInfos[i].UnitNameOffset); int globalId = (int)((unitIndexInfos[i].Offset - CandidateDataOffset) / WaveCandidateInfo.DataSize); for (int j = 0; j < unitIndexInfos[i].Count; ++j) { WaveCandidateInfo wci = new WaveCandidateInfo(); wci.Load(reader); _waveCandidates[i].Add(j, wci); wci.Id = j; wci.GlobalId = globalId + j; wci.Name = name; wci.SentenceId = _stringPool.GetString((int)wci.SentenceIdOffset); } } else { string name = string.Empty; if (invalidUnit == 1) { name = "hpl_SIL"; } else if (invalidUnit == 2) { name = "hpr_SIL"; } else { throw new InvalidDataException("There are more than 2 InvalidOffset unit, the number suppose be two: hpl_SIL and hpr_SIL."); } invalidUnit++; _namedUnitIndexId.Add(name, i); } } }
/// <summary> /// Saves the unit index and candidate data section to binary writer. /// </summary> /// <param name="writer">The given binary writer.</param> private void SaveCandidates(BinaryWriter writer) { // Unit index section. Debug.Assert(writer.BaseStream.Position == UnitIndexOffset, "This point is the unit index offset"); UnitIndexInfo indexInfo = new UnitIndexInfo { Offset = CandidateDataOffset }; for (int i = 0; i < UnitIndexCount; ++i) { if (_waveCandidates.ContainsKey(i)) { string unitName = _waveCandidates[i].First().Value.Name; // If the _waveCandidtes contains this id, it means there is some candidates belongs to this unit. Debug.Assert(_waveCandidates[i].Count > 0, "The wave candidtes count of unit should be greater than 0"); // Writes the unit index information. indexInfo.Count = (uint)_waveCandidates[i].Count; indexInfo.UnitNameOffset = _unitNameStringPoolOffsets[unitName]; indexInfo.Save(writer); // Moves the offset to the next unit. indexInfo.Offset += (uint)_waveCandidates[i].Count * WaveCandidateInfo.DataSize; } else { // If the _waveCandidtes doesn't contain the id, it means there is no candidate belongs to this unit. // For example, phoneme "silence" will have no candidates in RUS now. // However, in this case, a InvalidUnitIndexInfo should be written. UnitIndexInfo.InvalidIndexInfo.Save(writer); } } // Candidate data section. Debug.Assert(writer.BaseStream.Position == CandidateDataOffset, "This point is the candidate data offset"); int globalId = 0; for (int i = 0; i < UnitIndexCount; ++i) { if (_waveCandidates.ContainsKey(i)) { foreach (WaveCandidateInfo wci in _waveCandidates[i].Values) { wci.Save(writer); // double check the global ID if (wci.GlobalId != globalId) { throw new InvalidDataException( Helper.NeutralFormat("Global ID is not consistent, expect:{0}, real:{1}, unit:{2}, id:{3}", globalId, wci.GlobalId, wci.Name, wci.Id)); } globalId++; } } } }