/// <summary> /// Write out string pool with encrypt. /// </summary> /// <param name="stringPool">String pool.</param> /// <param name="writer">Binary data writer.</param> /// <returns>Size of bytes written out.</returns> public static uint Write(StringPool stringPool, DataWriter writer) { Helper.ThrowIfNull(stringPool); Helper.ThrowIfNull(writer); byte[] encryptedStringPool = new byte[stringPool.Length]; Microsoft.Tts.ServiceProvider.HTSVoiceDataEncrypt.EncryptStringPool( stringPool.ToArray(), encryptedStringPool); return writer.Write(encryptedStringPool); }
/// <summary> /// Write preselection node data. /// </summary> /// <param name="writer">The writer object.</param> /// <returns>Bytes written.</returns> public int Write(DataWriter writer) { int size = 0; size += (int)writer.Write(_candidateGroup.Id); var candidateIds = _candidateGroup.Candidates.Select(c => c.Id); Debug.Assert( !candidateIds.Any(x => x < 0), "Unsupported negative candiate Id."); bool[] values = new bool[candidateIds.Max() + 1]; foreach (var id in candidateIds) { values[id] = true; } BitArray bitArray = new BitArray(values); size += SetUtil.Write(SetType.IndexSet, bitArray, writer); return size; }
/// <summary> /// Save acoustic feakture variacne. /// </summary> /// <param name="outVarFile">Acoustic variance file.</param> /// <param name="writer">Binary data writer.</param> /// <returns>Size of bytes written out.</returns> public uint WriteOutVariance(string outVarFile, DataWriter writer) { Helper.ThrowIfFileNotExist(outVarFile); Helper.ThrowIfNull(writer); uint size = 0; IEnumerable<string> allLines = Helper.AllFileLines(outVarFile); size += writer.Write((uint)allLines.Count()); foreach (string line in allLines) { size += writer.Write(float.Parse(line)); } Debug.Assert(size % sizeof(uint) == 0, "Data must be 4-byte aligned."); return size; }
/// <summary> /// Save schema (with feature set and it's value group, mean, variance). /// </summary> /// <param name="language">The language.</param> /// <param name="schemaFile">The schema File.</param> /// <param name="phoneToIdIndexes">Phone To Id Indexes.</param> /// <param name="writer">Writer.</param> /// <param name="stringPool">String pool.</param> /// <returns>Size of bytes written out.</returns> public uint WriteSchema(Language language, string schemaFile, Dictionary<string, string> phoneToIdIndexes, DataWriter writer, StringPool stringPool) { Helper.ThrowIfFileNotExist(schemaFile); Helper.ThrowIfNull(phoneToIdIndexes); Helper.ThrowIfNull(writer); Helper.ThrowIfNull(stringPool); Helper.ThrowIfNull(language); uint size = 0; LexicalAttributeSchema schema = new LexicalAttributeSchema(language); schema.Load(schemaFile); List<string> stateFeatureList = new List<string>(); List<string> featureList = new List<string>(); int stateFeatureCount = 0; for (int i = 0; i < schema.Categories.Count; i++) { string name = schema.Categories[i].Name.ToLower(); if (name.IndexOf("state") >= 0) { stateFeatureCount++; if (!stateFeatureList.Contains(name)) { stateFeatureList.Add(name); } } if (!featureList.Contains(name)) { featureList.Add(name); } } // write state feature count. size += writer.Write((uint)stateFeatureList.Count); size += writer.Write((uint)stateFeatureCount); // write total feature count. size += writer.Write((uint)featureList.Count()); Dictionary<string, uint> featureIndex = new Dictionary<string, uint>(); uint index = 0; foreach (string feature in featureList) { size += writer.Write((uint)stringPool.Length); stringPool.PutString(feature); featureIndex.Add(feature, index++); } // write feature category size += writer.Write((uint)schema.Categories.Count); for (int i = 0; i < schema.Categories.Count; i++) { string featureName = schema.Categories[i].Name.ToLower(); // feature index size += writer.Write((uint)featureIndex[featureName]); // mean size += writer.Write(schema.Categories[i].Mean); // invStdDev size += writer.Write(schema.Categories[i].InvStdDev); // value count size += writer.Write((uint)schema.Categories[i].Values.Count); for (int k = 0; k < schema.Categories[i].Values.Count; k++) { string valueName = schema.Categories[i].Values[k].Name.ToLower(); string id = string.Empty; if (phoneToIdIndexes.ContainsKey(valueName) && featureName.IndexOf("phoneidentity") >= 0) { id = phoneToIdIndexes[valueName]; } else { id = valueName; } try { size += writer.Write(uint.Parse(id)); } catch (System.FormatException) { continue; } } } Debug.Assert(size % sizeof(uint) == 0, "Data must be 4-byte aligned."); return size; }
/// <summary> /// Write out linear transform. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="linXform">Linear transform.</param> /// <param name="streamOrder">The dynamic order of stream, to which the linear transform belongs.</param> /// <param name="hasBias">Indicate transform whether has bias info.</param> /// <param name="bandWidth">Band width of linear transform matrix.</param> /// <returns>Size of bytes written.</returns> protected virtual uint Write(DataWriter writer, LinXForm linXform, DynamicOrder streamOrder, bool hasBias, uint bandWidth) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(linXform); uint size = 0; Debug.Assert(Config.BiasBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); Debug.Assert(Config.MatrixBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); for (int i = 0; hasBias && i < linXform.VecSize; i++) { size += writer.Write(linXform.Bias[i]); } for (int i = 0; i < linXform.Blocks.Count; i++) { for (int j = 0; j < linXform.Blocks[i].GetLength(0); j++) { for (int k = 0; k < linXform.Blocks[i].GetLength(1); k++) { if (k >= j - bandWidth && k <= j + bandWidth) { size += writer.Write(linXform.Blocks[i][j, k]); } } } } return size; }
public void Save(string fontPath, HtsFontSerializer serializer, Dictionary<HmmModelType, int> xformBandWidths = null) { Helper.ThrowIfNull(fontPath); Helper.ThrowIfNull(serializer); Helper.EnsureFolderExistForFile(fontPath); using (FileStream fontStream = new FileStream(fontPath, FileMode.Create)) { using (DataWriter writer = new DataWriter(fontStream)) { uint size = serializer.Write(this, writer, xformBandWidths); Debug.Assert(size == fontStream.Length, "Calculated size of byte written out should equal with stream size."); } } }
/// <summary> /// Write the decision forest and tree index. /// </summary> /// <param name="forest">The decision forest.</param> /// <param name="treeIndexes">Tree indexes.</param> /// <param name="questionIndexes">Question indexes.</param> /// <param name="questionSet">The Question set.</param> /// <param name="namedOffsets">The named Offsets.</param> /// <param name="forestSerializer">The forest serializer.</param> /// <param name="writer">The writer to write.</param> /// <returns>The postion after write.</returns> internal int Write(DecisionForest forest, List<TreeIndex> treeIndexes, Dictionary<string, uint> questionIndexes, HtsQuestionSet questionSet, IDictionary<string, uint[]> namedOffsets, DecisionForestSerializer forestSerializer, DataWriter writer) { Helper.ThrowIfNull(forest); Helper.ThrowIfNull(treeIndexes); Helper.ThrowIfNull(writer); Helper.ThrowIfNull(questionIndexes); Helper.ThrowIfNull(questionSet); int decisionTreeSectionStart = (int)writer.BaseStream.Position; int position = decisionTreeSectionStart; // Write tree index (place holder) position += (int)WriteTreeIndexes(writer, treeIndexes.ToArray()); // Write trees for (int treeIndex = 0; treeIndex < forest.TreeList.Count; treeIndex++) { DecisionTree tree = forest.TreeList[treeIndex]; TreeIndex index = treeIndexes[treeIndex]; index.Offset = position - decisionTreeSectionStart; index.Size = (int)forestSerializer.Write(tree, writer, questionIndexes, namedOffsets); position += index.Size; } // Write tree index using (PositionRecover recover = new PositionRecover(writer, decisionTreeSectionStart, SeekOrigin.Begin)) { WriteTreeIndexes(writer, treeIndexes.ToArray()); } Debug.Assert(position % sizeof(uint) == 0, "Data should be 4-byte aligned."); return position - decisionTreeSectionStart; }
/// <summary> /// Writes font out into binary stream. /// </summary> /// <param name="font">NN font to write.</param> /// <param name="writer">Binary data.</param> /// <param name="language">Language.</param> /// <param name="schemaFile">Schema file.</param> /// <param name="outVarFile">Out var file.</param> /// <param name="phoneToIdIndexes">Phone id mapping.</param> /// <returns>Size of bytes written out.</returns> public uint Write(NNFont font, DataWriter writer, Language language, string schemaFile, string outVarFile, Dictionary<string, string> phoneToIdIndexes) { Helper.ThrowIfNull(font); Helper.ThrowIfNull(writer); Helper.ThrowIfNull(language); Helper.ThrowIfNull(phoneToIdIndexes); Helper.ThrowIfFileNotExist(schemaFile); Helper.ThrowIfFileNotExist(outVarFile); font.StringPool.Reset(); // write header. uint size = WriteFontHeader(font, writer); // write feature and variance. font.Header.QuestionOffset = size; font.Header.QuestionSize = Write(writer, font.StringPool, language, schemaFile, outVarFile, phoneToIdIndexes); size += font.Header.QuestionSize; // write model. font.Header.ModelSetOffset = size; font.Header.ModelSetSize = WriteModels(font, writer); size += font.Header.ModelSetSize; // write string pool. font.Header.StringPoolOffset = size; font.Header.StringPoolSize = Write(font.StringPool, writer); size += (uint)font.Header.StringPoolSize; font.Header.CodebookOffset = 0; font.Header.CodebookSize = 0; font.Header.FontSize = size - font.Header.FontSizeOffset; using (PositionRecover recover = new PositionRecover(writer, 0)) { font.Header.Write(writer); } return size; }
/// <summary> /// Writes font models out into binary stream. /// </summary> /// <param name="font">NN font to write.</param> /// <param name="writer">Binary data writer.</param> /// <returns>Size of bytes written out.</returns> private uint WriteModels(NNFont font, DataWriter writer) { Helper.ThrowIfNull(font); Helper.ThrowIfNull(writer); uint size = 0; // write positions. size += writer.Write(font.Models.Count); foreach (HmmModelType type in font.Models.Keys) { size += writer.Write((int)type); size += font.Models[type].Position.Save(writer); } // write windows. size += writer.Write(font.Models.Count - 1); foreach (HmmModelType type in font.Models.Keys) { if (type != HmmModelType.VoicedUnvoiced) { size += writer.Write((int)type); size += font.Models[type].WindowSet.Save(writer); } } return size; }
/// <summary> /// Write out Gaussian distribution. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussian">Gaussian.</param> /// <param name="streamOrder">The dynamic order of stream, to which the Gaussian belongs.</param> /// <returns>Size of bytes written.</returns> protected virtual uint Write(DataWriter writer, Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussian); uint size = 0; if (Config.HasWeight) { size += writer.Write((float)gaussian.Weight); } Debug.Assert(Config.MeanBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); Debug.Assert(Config.VarianceBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); for (int i = 0; Config.HasMean && i < gaussian.Length; i++) { Debug.Assert(Config.HasVariance, "Variance is needed to encode mean for runtime."); double invVar = CalculateInvertedVariance(gaussian.Variance[i], DefaultVarianceFloor); double mean = gaussian.Mean[i] * invVar; size += writer.Write((float)mean); } for (int i = 0; Config.HasVariance && i < gaussian.Length; i++) { double invVar = CalculateInvertedVariance(gaussian.Variance[i], DefaultVarianceFloor); size += writer.Write((float)invVar); } return size; }
public virtual uint Write(DataWriter writer, Gaussian[] gaussians, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussians); DataWriter orgWriter = writer; MemoryStream gaussiansBuf = null; if (EnableCompress) { gaussiansBuf = new MemoryStream(); writer = new DataWriter(gaussiansBuf); } uint size = 0; for (int i = 0; i < gaussians.Length; i++) { Statistic.Put(gaussians[i], streamOrder); size += WriteFourBytesAlignedGaussian(writer, gaussians[i], streamOrder); } if (EnableCompress) { size = orgWriter.Write(Encoder.Encode(gaussiansBuf.ToArray())); if (size % sizeof(uint) != 0) { size += orgWriter.Write(new byte[sizeof(uint) - (size % sizeof(uint))]); } writer = orgWriter; } return size; }
/// <summary> /// Write out Gaussian. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussian">Gaussian.</param> /// <param name="streamOrder">The dynamic order of stream, to which the Gaussian belongs.</param> /// <returns>Size of bytes written.</returns> protected override uint Write(DataWriter writer, Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussian); uint size = 0; Gaussian quantized = gaussian; if (IsNeedQuantize) { quantized = Quantize(gaussian, streamOrder); QuantizedStatistic.Put(quantized, streamOrder); } Debug.Assert(Config.MeanBits == sizeof(short) * 8, "Only 16-bit short value is supported here"); for (int i = 0; Config.HasMean && i < gaussian.Length; i++) { size += writer.Write((short)quantized.Mean[i]); } Debug.Assert(Config.VarianceBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); for (int i = 0; Config.HasVariance && i < gaussian.Length; i++) { size += writer.Write((byte)quantized.Variance[i]); } return size; }
/// <summary> /// Save pre-selection forest. /// </summary> /// <param name="decisionForest">The forest with each tree corresponding to a unit.</param> /// <param name="candidateGroups">The candidate group collection.</param> /// <param name="unitCandidateNameIds">Given candidate idx.</param> /// <param name="customFeatures">Cusotmized linguistic feature list.</param> /// <param name="outputPath">The output path.</param> public void Write(DecisionForest decisionForest, ICollection<CandidateGroup> candidateGroups, IDictionary<string, int> unitCandidateNameIds, HashSet<string> customFeatures, string outputPath) { foreach (Question question in decisionForest.QuestionList) { question.Language = _phoneSet.Language; question.ValueSetToCodeValueSet(_posSet, _phoneSet, customFeatures); } FileStream file = new FileStream(outputPath, FileMode.Create); try { using (DataWriter writer = new DataWriter(file)) { file = null; uint position = 0; // Write header section place holder PreselectionFileHeader header = new PreselectionFileHeader(); position += (uint)header.Write(writer); HtsFontSerializer serializer = new HtsFontSerializer(); // Write feature, question and prepare string pool HtsQuestionSet questionSet = new HtsQuestionSet { Items = decisionForest.QuestionList, Header = new HtsQuestionSetHeader { HasQuestionName = false }, CustomFeatures = customFeatures, }; using (StringPool stringPool = new StringPool()) { Dictionary<string, uint> questionIndexes = new Dictionary<string, uint>(); header.QuestionOffset = position; header.QuestionSize = serializer.Write( questionSet, writer, stringPool, questionIndexes, customFeatures); position += header.QuestionSize; // Write leaf referenced data to buffer IEnumerable<INodeData> dataNodes = GetCandidateNodes(candidateGroups); using (MemoryStream candidateSetBuffer = new MemoryStream()) { Dictionary<string, int> namedSetOffset = new Dictionary<string, int>(); int candidateSetSize = HtsFontSerializer.Write( dataNodes, new DataWriter(candidateSetBuffer), namedSetOffset); // Write decision forest Dictionary<string, uint[]> namedOffsets = namedSetOffset.ToDictionary(p => p.Key, p => new[] { (uint)p.Value }); header.DecisionTreeSectionOffset = position; header.DecisionTreeSectionSize = (uint)Write(decisionForest, unitCandidateNameIds, questionIndexes, questionSet, namedOffsets, new DecisionForestSerializer(), writer); position += header.DecisionTreeSectionSize; // Write string pool header.StringPoolOffset = position; header.StringPoolSize = HtsFontSerializer.Write(stringPool, writer); position += header.StringPoolSize; // Write leaf referenced data header.CandidateSetSectionOffset = position; header.CandidateSetSectionSize = writer.Write(candidateSetBuffer.ToArray()); position += header.CandidateSetSectionSize; } // Write header section place holder using (PositionRecover recover = new PositionRecover(writer, 0)) { header.Write(writer); } } } } finally { if (null != file) { file.Dispose(); } } }
/// <summary> /// Write out one linear transform to be 4-byte aligned. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="linXform">Linear transform to write out.</param> /// <param name="streamOrder">Dynamic order of the stream of current linear transform.</param> /// <param name="hasBias">Indicate transform whether has bias info.</param> /// <param name="bandWidth">Band width of linear transform matrix.</param> /// <returns>Number of bytes written out.</returns> protected uint WriteFourBytesAlignedLinXform(DataWriter writer, LinXForm linXform, DynamicOrder streamOrder, bool hasBias, uint bandWidth = 0) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(linXform); uint size = Write(writer, linXform, streamOrder, hasBias, bandWidth); if (size == 0) { throw new InvalidDataException(Helper.NeutralFormat("Zero length of linXform is not allowed.")); } // Pad zero bytes if needed to align with 4-bytes if (size % sizeof(uint) > 0) { size += writer.Write(new byte[sizeof(uint) - (size % sizeof(uint))]); } Debug.Assert(size % sizeof(uint) == 0, "Data should be 4-byte aligned."); return size; }
/// <summary> /// Writes font header into binary stream. /// </summary> /// <param name="font">Font to write.</param> /// <param name="writer">Data binary writer.</param> /// <returns>Size of bytes written out.</returns> protected virtual uint WriteFontHeader(NNFont font, DataWriter writer) { Helper.ThrowIfNull(font); Helper.ThrowIfNull(writer); return font.Header.Write(writer); }
/// <summary> /// Write out locations. /// </summary> /// <param name="locations">Locations to write.</param> /// <param name="writer">Binary data writer.</param> /// <returns>Size of bytes written.</returns> private static uint Write(Location[] locations, DataWriter writer) { Helper.ThrowIfNull(locations); Helper.ThrowIfNull(writer); uint size = writer.Write(locations.Length); for (int i = 0; i < locations.Length; i++) { size += writer.Write(locations[i].Offset); size += writer.Write(locations[i].Length); } return size; }
/// <summary> /// Write out one Gaussian distribution to be 4-byte aligned. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussian">Gaussian distribution to write out.</param> /// <param name="streamOrder">Dynamic order of the stream of current Gaussian distribution.</param> /// <returns>Number of bytes written out.</returns> protected uint WriteFourBytesAlignedGaussian(DataWriter writer, Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussian); uint size = Write(writer, gaussian, streamOrder); if (size == 0) { throw new InvalidDataException(Helper.NeutralFormat("Zero length of Gaussian is not allowed.")); } // Pad zero bytes if needed to align with 4-bytes if (size % sizeof(uint) > 0) { size += writer.Write(new byte[sizeof(uint) - (size % sizeof(uint))]); } Debug.Assert(size % sizeof(uint) == 0, "Data should be 4-byte aligned."); return size; }
/// <summary> /// Write out Gaussians of one stream. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussians">Gaussians.</param> /// <param name="streamOrder">The dynamic order of stream, to which the Gaussian belongs.</param> /// <returns>Size of bytes written.</returns> public override uint Write(DataWriter writer, Gaussian[] gaussians, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussians); if (gaussians.Count(g => g.Length > 0) != 1) { string message = string.Format(CultureInfo.InvariantCulture, "Multi-space distribution with [{0}] non-zero-length mixtures is not supported", gaussians.Count(g => g.Length > 0)); throw new InvalidDataException(message); } // Maximum dimension among Gaussian models in this stream int maxDimension = gaussians.Max(g => g.Length); uint size = 0; Debug.Assert(gaussians.Count(g => g.Length == maxDimension) == 1, "The number of meaningful MSD mixture number should be 1"); for (int i = 0; i < gaussians.Length; i++) { if (gaussians[i].Length == maxDimension) { Statistic.Put(gaussians[i], streamOrder); size += WriteFourBytesAlignedGaussian(writer, gaussians[i], streamOrder); } } return size; }
/// <summary> /// Write out Gaussian. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussian">Gaussian.</param> /// <param name="streamOrder">The dynamic order of stream, to which the Gaussian belongs.</param> /// <returns>Size of bytes written.</returns> protected override uint Write(DataWriter writer, Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussian); uint size = 0; Gaussian quantized = gaussian; if (IsNeedQuantize) { quantized = Quantize(gaussian, streamOrder); QuantizedStatistic.Put(quantized, streamOrder); } if (Config.HasWeight) { if (quantized.Weight == 0.0f) { throw new InvalidDataException(Helper.NeutralFormat("Zero weight of LogF0 is found.")); } size += writer.Write((float)quantized.Weight); } Debug.Assert(Config.MeanBits == sizeof(short) * 8, "Only 16-bit short value is supported here"); for (int i = 0; Config.HasMean && i < gaussian.Length; i++) { size += writer.Write((short)quantized.Mean[i]); } Debug.Assert(Config.VarianceBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); for (int i = 0; Config.HasVariance && i < gaussian.Length; i++) { size += writer.Write((byte)quantized.Variance[i]); } return size; }
/// <summary> /// Write the pst data. /// </summary> /// <param name="pstFile">The pst file name to be stored.</param> /// <param name="data">The pst data to be write.</param> /// <param name="ttsPhoneSet">The tts Phone set.</param> /// <param name="ttsPosSet">The tts pst set.</param> public void WritePSTData(string pstFile, PSTData data, TtsPhoneSet ttsPhoneSet, TtsPosSet ttsPosSet) { foreach (Question question in data.DecisionForest.QuestionList) { question.Language = ttsPhoneSet.Language; question.ValueSetToCodeValueSet(ttsPosSet, ttsPhoneSet, data.CustomFeatures); } FileStream file = new FileStream(pstFile, FileMode.Create); try { using (DataWriter writer = new DataWriter(file)) { file = null; uint position = 0; // Write header section place holder PreselectionFileHeader header = new PreselectionFileHeader(); position += (uint)header.Write(writer); HtsFontSerializer serializer = new HtsFontSerializer(); using (StringPool stringPool = new StringPool()) { Dictionary<string, uint> questionIndexes = new Dictionary<string, uint>(); header.QuestionOffset = position; header.QuestionSize = serializer.Write( data.QuestionSet, writer, stringPool, questionIndexes, data.CustomFeatures); position += header.QuestionSize; // Write leaf referenced data to buffer List<CandidateSetData> dataNodes = data.CadidateSets; int val = data.CadidateSets.Sum(c => c.Candidates.Count); using (MemoryStream candidateSetBuffer = new MemoryStream()) { Dictionary<string, int> namedSetOffset = new Dictionary<string, int>(); int candidateSetSize = HtsFontSerializer.Write( dataNodes, new DataWriter(candidateSetBuffer), namedSetOffset); // Write decision forest Dictionary<string, uint[]> namedOffsets = namedSetOffset.ToDictionary(p => p.Key, p => new[] { (uint)p.Value }); header.DecisionTreeSectionOffset = position; header.DecisionTreeSectionSize = (uint)Write(data.DecisionForest, data.TreeIndexes, questionIndexes, data.QuestionSet, namedOffsets, new DecisionForestSerializer(), writer); position += header.DecisionTreeSectionSize; // Write string pool header.StringPoolOffset = position; header.StringPoolSize = HtsFontSerializer.Write(stringPool, writer); position += header.StringPoolSize; // Write leaf referenced data header.CandidateSetSectionOffset = position; header.CandidateSetSectionSize = writer.Write(candidateSetBuffer.ToArray()); position += header.CandidateSetSectionSize; } // Write header section place holder using (PositionRecover recover = new PositionRecover(writer, 0)) { header.Write(writer); } } } } finally { if (null != file) { file.Dispose(); } } }
/// <summary> /// Write out Gaussian. /// </summary> /// <param name="writer">Binary writer.</param> /// <param name="gaussian">Gaussian.</param> /// <param name="streamOrder">The dynamic order of stream, to which the Gaussian belongs.</param> /// <returns>Size of bytes written.</returns> protected override uint Write(DataWriter writer, Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(gaussian); uint size = 0; Gaussian quantized = gaussian; if (IsNeedQuantize) { quantized = Quantize(gaussian); QuantizedStatistic.Put(quantized, streamOrder); } if (Config.HasWeight) { size += writer.Write((float)quantized.Weight); } if (!Config.HasMean || !Config.HasVariance) { throw new InvalidDataException("Needs both mean and variance."); } for (int i = 0; i < quantized.Length; i++) { if ((i + 1) % Config.StaticVectorSize == 0) { size += writer.Write((short)quantized.Mean[i]); } else if (i < Config.StaticVectorSize) { size += writer.Write((byte)quantized.Mean[i]); } else { size += writer.Write((sbyte)quantized.Mean[i]); } } for (int i = 0; i < gaussian.Length; i++) { size += writer.Write((byte)quantized.Variance[i]); } return size; }
/// <summary> /// Write tree indexes. /// </summary> /// <param name="writer">The writer object.</param> /// <param name="treeIndexes">The tree index array.</param> /// <returns>Bytes written.</returns> private uint WriteTreeIndexes(DataWriter writer, TreeIndex[] treeIndexes) { uint size = 0; // Write tree count size += writer.Write((uint)treeIndexes.Length); foreach (TreeIndex index in treeIndexes) { size += writer.Write(index.Id); size += writer.Write(index.Offset); size += writer.Write(index.Size); } return size; }
/// <summary> /// Save feature set. /// </summary> /// <param name="writer">Binary data writer.</param> /// <param name="stringPool">String pool.</param> /// <param name="language">Language.</param> /// <param name="schemaFile">Schema file.</param> /// <param name="outVarFile">Out var file.</param> /// <param name="phoneToIdIndexes">Phone id mapping.</param> /// <returns>Size of bytes written out.</returns> public uint Write(DataWriter writer, StringPool stringPool, Language language, string schemaFile, string outVarFile, Dictionary<string, string> phoneToIdIndexes) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(language); Helper.ThrowIfNull(phoneToIdIndexes); Helper.ThrowIfFileNotExist(schemaFile); Helper.ThrowIfFileNotExist(outVarFile); uint size = 0; size += WriteSchema(language, schemaFile, phoneToIdIndexes, writer, stringPool); size += WriteOutVariance(outVarFile, writer); Debug.Assert(size % sizeof(uint) == 0, "Data must be 4-byte aligned."); return size; }
/// <summary> /// Writes HTS font header into binary stream. /// </summary> /// <param name="writer">Binary writer.</param> /// <returns>Size of bytes written.</returns> public uint Write(DataWriter writer) { Helper.ThrowIfNull(writer); byte[] buff = ToBytes(); uint size = writer.Write(buff); #if SERIALIZATION_CHECKING ConsistencyChecker.Check(this, Read(writer.BaseStream.Excerpt(size))); #endif return size; }
public virtual uint Write(DataWriter writer, LinXForm meanXform, LinXForm varXform, DynamicOrder streamOrder) { Helper.ThrowIfNull(writer); Helper.ThrowIfNull(meanXform); Helper.ThrowIfNull(varXform); DataWriter orgWriter = writer; MemoryStream linXformsBuf = null; if (EnableCompress) { linXformsBuf = new MemoryStream(); writer = new DataWriter(linXformsBuf); } uint size = 0; if (Config.HasMeanXform) { MeanStatistic.Put(meanXform, streamOrder); size += WriteFourBytesAlignedLinXform(writer, meanXform, streamOrder, Config.HasMeanBias, Config.MeanBandWidth); } if (Config.HasVarXform) { VarStatistic.Put(varXform, streamOrder); size += WriteFourBytesAlignedLinXform(writer, varXform, streamOrder, Config.HasVarBias); } if (EnableCompress) { size = orgWriter.Write(Encoder.Encode(linXformsBuf.ToArray())); if (size % sizeof(uint) != 0) { size += orgWriter.Write(new byte[sizeof(uint) - (size % sizeof(uint))]); } writer = orgWriter; } return size; }