/// <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>
        /// 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 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);
 }