/// <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> /// Test whether two Gaussian lists are equal. /// </summary> /// <param name="lefts">Left list.</param> /// <param name="rights">Right list.</param> /// <param name="comareData">To compare data.</param> /// <returns>True if yes, otherwise false.</returns> public static bool IsEqual(Gaussian[] lefts, Gaussian[] rights, bool comareData) { Helper.ThrowIfNull(lefts); Helper.ThrowIfNull(rights); List<Gaussian> leftList = new List<Gaussian>(lefts.Where(g => g.Length > 0)); List<Gaussian> rightList = new List<Gaussian>(rights.Where(g => g.Length > 0)); if (leftList.Count != rightList.Count) { return false; } for (int i = 0; i < leftList.Count; i++) { if (!IsEqual(leftList[i], rightList[i], comareData)) { return false; } } return true; }
/// <summary> /// Puts a sample into this list. /// </summary> /// <param name="gaussian">Gaussian distribution.</param> /// <param name="streamOrder">Dynamic stream order.</param> public void Put(Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(gaussian); if (!GuassianStatistics.ContainsKey(streamOrder)) { GuassianStatistics.Add(streamOrder, new GaussianStatistic(gaussian.Length)); } GuassianStatistics[streamOrder].Put(gaussian); }
/// <summary> /// Quantize means and variances in Gaussian distribution into value range of fixed point numerical representation. /// </summary> /// <param name="gaussian">Gaussian distribution to quantize.</param> /// <returns>Quantized Gaussian distribution.</returns> private Gaussian Quantize(Gaussian gaussian) { Helper.ThrowIfNull(gaussian); Gaussian quantized = new Gaussian(); quantized.Weight = gaussian.Weight; quantized.Length = gaussian.Length; quantized.Variance = new double[gaussian.Length]; quantized.Mean = new double[gaussian.Length]; short lastQuantizedMean = 0; for (int i = 0; i < gaussian.Length; i++) { if ((i + 1) % Config.StaticVectorSize == 0) { // Gain double mean = NormalizeToOne(gaussian.Mean[i], GainMaximumMean) * short.MaxValue; mean = Clip(short.MinValue, Math.Round(mean), short.MaxValue); quantized.Mean[i] = (short)mean; } else if (i < Config.StaticVectorSize) { // Quantize the delta of LSF for static dimensions double quantizedMean = gaussian.Mean[i] * short.MaxValue; quantizedMean /= _staticLsfMeanDownScaleTo256Factor; short deltaOfTwoLsf = (short)Clip((short)1, Math.Round(quantizedMean - lastQuantizedMean), (short)byte.MaxValue); lastQuantizedMean = (short)(lastQuantizedMean + deltaOfTwoLsf); quantized.Mean[i] = (byte)deltaOfTwoLsf; } else { // Quantize LSF for non-static dimensions double quantizedMean = gaussian.Mean[i] * short.MaxValue / _nonStaticLsfMeanDownScaleFactor; quantizedMean = (float)Clip(sbyte.MinValue, Math.Round(quantizedMean), sbyte.MaxValue); quantized.Mean[i] = (sbyte)quantizedMean; } } for (int i = 0; i < gaussian.Length; i++) { double invVar = CalculateInvertedVariance(gaussian.Variance[i], DefaultVarianceFloor); if ((i + 1) % Config.StaticVectorSize == 0) { // Gain invVar *= GainUpScaleFactor; } else { invVar /= LsfDownScaleFactor; } if (i >= Config.StaticVectorSize) { invVar /= byte.MaxValue; } invVar = Clip(1, Math.Round(Math.Sqrt(invVar)), byte.MaxValue); Debug.Assert((byte)invVar > 0); quantized.Variance[i] = (byte)invVar; } return quantized; }
/// <summary> /// Reads one HMM gaussian instance from text reader instance. /// </summary> /// <param name="rewinder">The text reader to read gaussian from.</param> /// <returns>HMM gaussian instance loaded.</returns> private static Gaussian ReadGaussian(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); Gaussian gaussian = new Gaussian(); gaussian.Mean = ReadTagArray(rewinder, "<MEAN>"); gaussian.Variance = ReadTagArray(rewinder, "<VARIANCE>"); if (gaussian.Mean.Length != gaussian.Variance.Length) { throw new InvalidDataException(Helper.NeutralFormat( "The dimension of mean [{0}] should equal with that of variance [{1}].", gaussian.Mean.Length, gaussian.Variance.Length)); } gaussian.Length = gaussian.Mean.Length; string line = rewinder.PeekLine(); if (line != null && line.StartsWith("<GCONST>")) { string[] items = ParseTagValues(rewinder.ReadLine(), "<GCONST>"); if (items.Length != 1) { throw new InvalidDataException(Helper.NeutralFormat( "Single value is expected for <GCONST>, but it is with line [{0}].", line)); } gaussian.GlobalConstant = float.Parse(items[0], CultureInfo.InvariantCulture); } return gaussian; }
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); 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> /// Read Gaussian distribution. /// </summary> /// <param name="reader">Binary reader to read Gaussian distributions.</param> /// <param name="dimension">Dimension of the Gaussian distribution to read.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>Gaussian distribution.</returns> protected override Gaussian ReadGaussian(BinaryReader reader, int dimension, DynamicOrder streamOrder) { Helper.ThrowIfNull(reader); Gaussian gaussian = new Gaussian(); gaussian.Length = dimension; Debug.Assert(Config.MeanBits == sizeof(short) * 8, "Only 16-bit short value is supported here"); gaussian.Mean = new double[gaussian.Length]; for (int i = 0; i < gaussian.Length; i++) { gaussian.Mean[i] = reader.ReadInt16(); } Debug.Assert(Config.VarianceBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); gaussian.Variance = new double[gaussian.Length]; for (int i = 0; Config.HasVariance && i < gaussian.Length; i++) { gaussian.Variance[i] = (int)reader.ReadByte(); } if (IsNeedQuantize) { gaussian = Dequantize(gaussian, streamOrder); } return gaussian; }
/// <summary> /// Puts a sample into statistics. /// </summary> /// <param name="gaussian">Gaussian distribution.</param> public void Put(Gaussian gaussian) { Helper.ThrowIfNull(gaussian); for (int i = 0; i < gaussian.Length; i++) { Mean[i].Put(gaussian.Mean[i]); Variance[i].Put(gaussian.Variance[i]); } }
/// <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> /// De-quantize Gaussian distribution of LSP model. /// </summary> /// <param name="gaussian">Gaussian distribution to de-quantize.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>De-quantized Gaussian distribution.</returns> private Gaussian Dequantize(Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(gaussian); Gaussian result = new Gaussian(); result.Length = gaussian.Length; result.Weight = gaussian.Weight; result.Mean = new double[gaussian.Length]; result.Variance = new double[gaussian.Length]; Debug.Assert(Config.MeanBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); double accumulatedMean = 0.0f; for (int i = 0; i < gaussian.Length; i++) { if ((i + 1) % Config.StaticVectorSize == 0) { // Gain result.Mean[i] = (double)(gaussian.Mean[i] * GainMaximumMean) / short.MaxValue; } else if (i < Config.StaticVectorSize) { accumulatedMean += (double)(gaussian.Mean[i] * _staticLsfMeanDownScaleTo256Factor) / short.MaxValue; result.Mean[i] = accumulatedMean; } else { result.Mean[i] = (double)(gaussian.Mean[i] * _nonStaticLsfMeanDownScaleFactor) / short.MaxValue; } } Debug.Assert(Config.VarianceBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); for (int i = 0; i < gaussian.Length; i++) { double value = (int)gaussian.Variance[i]; value = (double)(value * value); if (i >= Config.StaticVectorSize) { value *= byte.MaxValue; } if ((i + 1) % Config.StaticVectorSize == 0) { // Gain value /= GainUpScaleFactor; } else { value *= LsfDownScaleFactor; } result.Variance[i] = 1.0f / value; } return result; }
/// <summary> /// Tell whether two HMM Gaussian distributions equals with each other. /// </summary> /// <param name="left">Left Gaussian distribution.</param> /// <param name="right">Right Gaussian distribution.</param> /// <param name="comareData">Flag to indicate whether comparing data in Gaussian distribution.</param> /// <returns>True if equal, otherwise false.</returns> public static bool IsEqual(Gaussian left, Gaussian right, bool comareData) { Helper.ThrowIfNull(left); Helper.ThrowIfNull(right); return (float.IsNaN(left.Weight) || float.IsNaN(right.Weight) || left.Weight == right.Weight) && left.Length == right.Length && IsEqual(left.Mean, right.Mean, comareData) && IsEqual(left.Variance, right.Variance, comareData); }
/// <summary> /// Quantize means and variances in Gaussian distribution into value range of fixed point numerical representation. /// </summary> /// <param name="gaussian">Gaussian distribution to quantize.</param> /// <param name="streamOrder">Stream order of current Gaussian distribution to quantize.</param> /// <returns>Quantized Gaussian distribution.</returns> private Gaussian Quantize(Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(gaussian); Gaussian quantized = new Gaussian(gaussian.Weight, gaussian.Length); for (int i = 0; Config.HasMean && i < gaussian.Length; i++) { double mean = (double)gaussian.Mean[i] / MaxLogF0DownScaleFactor * MeanUpScaleAsShortFactor; quantized.Mean[i] = (short)Clip(short.MinValue, Math.Round(mean), short.MaxValue); } 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++) { double invVar = CalculateInvertedVariance(gaussian.Variance[i], DefaultVarianceFloor); if (streamOrder != DynamicOrder.Static && i >= Config.StaticVectorSize) { // Treat non-static features differently as it has bigger range invVar /= byte.MaxValue; } else { invVar *= StaticVarianceUpscaleFactor; } invVar = Math.Sqrt(invVar); quantized.Variance[i] = (byte)Clip(1, Math.Round(invVar), byte.MaxValue); Debug.Assert(quantized.Variance[i] >= 1); } return quantized; }
/// <summary> /// Read Gaussian distributions. /// </summary> /// <param name="reader">Binary reader to read Gaussian distributions.</param> /// <param name="dimension">Dimension of the Gaussian distribution to read.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>Gaussian distributions.</returns> public virtual Gaussian[] ReadGaussians(BinaryReader reader, int dimension, DynamicOrder streamOrder) { Helper.ThrowIfNull(reader); long orgPos = reader.BaseStream.Position; Gaussian[] gaussians = new Gaussian[Config.MixtureCount]; for (uint i = 0; i < Config.MixtureCount; i++) { gaussians[i] = ReadFourBytesAlignedGaussian(reader, dimension, streamOrder); } if (Encoder != null) { // ramp up the encoder long size = reader.BaseStream.Position - orgPos; reader.BaseStream.Position = orgPos; Encoder.WarmUpData(reader.ReadBytes((int)size), 1); } return gaussians; }
/// <summary> /// De-quantize Gaussian distribution of LogF0 model. /// </summary> /// <param name="gaussian">Gaussian distribution to de-quantize.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>De-quantized Gaussian distribution.</returns> private Gaussian Dequantize(Gaussian gaussian, DynamicOrder streamOrder) { Helper.ThrowIfNull(gaussian); Gaussian result = new Gaussian(gaussian.Weight, gaussian.Length); Debug.Assert(Config.MeanBits == sizeof(short) * 8, "Only 16-bit short value is supported here"); for (int i = 0; i < gaussian.Length; i++) { result.Mean[i] = (double)(gaussian.Mean[i] * MaxLogF0DownScaleFactor) / MeanUpScaleAsShortFactor; } 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++) { double value = (int)gaussian.Variance[i]; if (i >= Config.StaticVectorSize && streamOrder != DynamicOrder.Static) { value = (double)(value * value); value *= byte.MaxValue; } result.Variance[i] = 1.0f / value; } return result; }
/// <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; }
/// <summary> /// Read Gaussian distribution. /// </summary> /// <param name="reader">Binary reader to read Gaussian distributions.</param> /// <param name="dimension">Dimension of the Gaussian distribution to read.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>Gaussian distribution.</returns> protected override Gaussian ReadGaussian(BinaryReader reader, int dimension, DynamicOrder streamOrder) { Helper.ThrowIfNull(reader); Gaussian gaussian = new Gaussian(); gaussian.Length = dimension; gaussian.Weight = Config.HasWeight ? reader.ReadSingle() : float.NaN; Debug.Assert(Config.MeanBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); gaussian.Mean = new double[gaussian.Length]; for (int i = 0; i < gaussian.Length; i++) { if ((i + 1) % Config.StaticVectorSize == 0) { // Gain gaussian.Mean[i] = reader.ReadInt16(); } else if (i < Config.StaticVectorSize) { gaussian.Mean[i] = reader.ReadByte(); } else { gaussian.Mean[i] = reader.ReadSByte(); } } Debug.Assert(Config.VarianceBits == sizeof(byte) * 8, "Only 8-bit byte value is supported here"); gaussian.Variance = new double[gaussian.Length]; for (int i = 0; i < gaussian.Length; i++) { gaussian.Variance[i] = reader.ReadByte(); } if (IsNeedQuantize) { gaussian = Dequantize(gaussian, streamOrder); } return gaussian; }
/// <summary> /// Read Gaussian distribution. /// </summary> /// <param name="reader">Binary reader to read Gaussian distributions.</param> /// <param name="dimension">Dimension of the Gaussian distribution to read.</param> /// <param name="streamOrder">The dynamic order of current Gaussian distribution to read.</param> /// <returns>Gaussian distribution.</returns> protected virtual Gaussian ReadGaussian(BinaryReader reader, int dimension, DynamicOrder streamOrder) { Helper.ThrowIfNull(reader); Gaussian gaussian = new Gaussian(); gaussian.Length = dimension; gaussian.Weight = Config.HasWeight ? reader.ReadSingle() : float.NaN; if (Config.HasMean) { if (!Config.HasVariance) { throw new InvalidDataException(Helper.NeutralFormat("Variance is needed as Mean depends on that.")); } Debug.Assert(Config.MeanBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); gaussian.Mean = new double[gaussian.Length]; for (int i = 0; i < gaussian.Length; i++) { gaussian.Mean[i] = reader.ReadSingle(); } } if (Config.HasVariance) { Debug.Assert(Config.VarianceBits == sizeof(float) * 8, "Only 32-bit float value is supported here"); gaussian.Variance = new double[gaussian.Length]; for (int i = 0; i < gaussian.Length; i++) { gaussian.Variance[i] = reader.ReadSingle(); gaussian.Variance[i] = 1.0f / gaussian.Variance[i]; // Revert back } } if (Config.HasMean) { for (int i = 0; i < gaussian.Length; i++) { gaussian.Mean[i] *= gaussian.Variance[i]; // Revert back } } return gaussian; }
/// <summary> /// Converts the HMM gaussian instance into string in MMF format. /// </summary> /// <param name="gaussian">The gaussian instance to convert.</param> /// <returns>Gaussian instance in string format.</returns> private static string ToString(Gaussian gaussian) { Helper.ThrowIfNull(gaussian); StringBuilder builder = new StringBuilder(); if (gaussian.Length == 0) { builder.AppendFormat(CultureInfo.InvariantCulture, "<MEAN> 0{0}<VARIANCE> 0{0}", Environment.NewLine); builder.AppendFormat(CultureInfo.InvariantCulture, "<GCONST> {1:e6}{0}", Environment.NewLine, gaussian.GlobalConstant); } else { builder.AppendFormat(CultureInfo.InvariantCulture, "<MEAN> {1}{0} {2}{0}<VARIANCE> {3}{0} {4}{0}", Environment.NewLine, gaussian.Mean.Length, gaussian.Mean.Select(v => v.ToString("e6", CultureInfo.InvariantCulture)).Concatenate(" "), gaussian.Variance.Length, gaussian.Variance.Select(v => v.ToString("e6", CultureInfo.InvariantCulture)).Concatenate(" ")); if (gaussian.GlobalConstant != 0.0f) { builder.AppendFormat(CultureInfo.InvariantCulture, "<GCONST> {1:e6}{0}", Environment.NewLine, gaussian.GlobalConstant); } } return builder.ToString(); }
/// <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> /// Detects gaussian distribution type according gaussians. /// </summary> /// <param name="gaussians">Gaussians.</param> /// <returns>Gaussian distribution type.</returns> private static ModelDistributionType DetectDistribution(Gaussian[] gaussians) { Helper.ThrowIfNull(gaussians); ModelDistributionType type = ModelDistributionType.NotDefined; if (gaussians.Length == 2) { if (gaussians[1].Mean.Count(m => m != 0) == 0 && gaussians[1].Variance.Count(m => m != 0) == 0) { type = ModelDistributionType.Msd; } } return type; }
/// <summary> /// Get a Gaussian distribution. /// </summary> /// <returns>Gaussian distribution.</returns> public Gaussian[] ReadGaussian() { HmmSymbol symbol; int mixtureCount = 1; if ((symbol = ReadNextSymbol()) != HmmSymbol.Mean) { if ((symbol = ReadNextSymbol()) == HmmSymbol.NumMixes) { mixtureCount = _hmmbr.ReadInt32(); } } Gaussian[] stream = new Gaussian[mixtureCount]; // Get Gaussian parameters. for (int i = 0; i < mixtureCount; i++) { if (symbol != HmmSymbol.Mean) { // Get weight. symbol = ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.Mixture); _hmmbr.ReadInt16(); stream[i].Weight = _hmmbr.ReadSingle(); symbol = ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.Mean); } else { stream[i].Weight = 1.0f; } stream[i].Mean = ReadFloatArray(); stream[i].Length = stream[i].Mean.Length; symbol = ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.Variance); stream[i].Variance = ReadFloatArray(); Debug.Assert(stream[i].Length == stream[i].Variance.Length); symbol = ReadNextSymbol(); Debug.Assert(symbol == HmmSymbol.GConst); stream[i].GlobalConstant = _hmmbr.ReadSingle(); } return stream; }