private void EmitE3Mappings(WriteBitDelegate bitWriter, bool value) { // perform e3 mappings for (; _scale > 0; _scale--) { bitWriter(value); } }
/// <summary> /// Writes the bit representation of <paramref name="symbol" /> with <paramref name="bitWriter" />. /// </summary> public void WriteCode(TSymbolType symbol, WriteBitDelegate bitWriter) { var bits = GetCachedBits(symbol); for (var i = 0; i < bits.Length; ++i) { bitWriter(bits[i]); } }
/// <summary> /// Writes the code for the entry at <paramref name="index" /> to <paramref name="bitWriter" />. /// </summary> private void WriteCode(uint index, WriteBitDelegate bitWriter) { if (_entries.Length > 1) { var parentIndex = _entries[index].ParentIndex; if (parentIndex != Root) { WriteCode(parentIndex, bitWriter); } bitWriter(_entries[parentIndex].GetBit(index)); } }
/// <summary> /// Encodes <paramref name="symbol"/> using the <paramref name="coder"/> with /// the provided <paramref name="model"/>. /// </summary> public static void Encode <TSymbolType>(this ArithmeticCoder coder, TSymbolType symbol, IModel <TSymbolType> model, WriteBitDelegate bitWriter) where TSymbolType : struct { // cumulate frequencies Range count = model.GetRange(symbol); // encode symbol coder.Encode(count, model.TotalFrequencies, bitWriter); // update model model.Update(symbol); }
/// <summary> /// Encodes the range updating the state of the encoder. /// </summary> public void Encode(Range counts, uint total, WriteBitDelegate bitWriter) // total < 2^29 { if (total >= RangeLimit) { throw new ArgumentOutOfRangeException("total"); } if (counts.Low >= RangeLimit || counts.High >= RangeLimit) { throw new ArgumentOutOfRangeException("counts"); } if (counts.Low >= counts.High) { throw new ArgumentException("counts"); } if (bitWriter == null) { throw new ArgumentNullException("bitWriter"); } // partition number space into single steps _step = (_range.Length()) / total; // interval open at the top => +1 // Update bounds -- interval open at the top => -1 for High. _range = (counts * _step + _range.Low) - BoundaryAdjust; // apply e1/e2 mapping while ((_range.High < Half) || (_range.Low >= Half)) { bool isHighLessThanHalf = _range.High < Half; // true => emit false for lower half. uint sub = isHighLessThanHalf ? 0 : Half; bitWriter(!isHighLessThanHalf); EmitE3Mappings(bitWriter, isHighLessThanHalf); _range = (_range - sub) * 2 + BoundaryAdjust; } // e3 while (_range.In(FirstQuarter, ThirdQuarter)) { // keep necessary e3 mappings in mind _scale++; _range = (_range - FirstQuarter) * 2 + BoundaryAdjust; } }
/// <summary> /// Finishes encoding, writing any remaining bits. /// </summary> /// <param name="bitWriter"></param> public void EncodeFinish(WriteBitDelegate bitWriter) { if (bitWriter == null) { throw new ArgumentNullException("bitWriter"); } // There are two possibilities of how _range.Low and _range.High can be distributed, // which means that two bits are enough to distinguish them. bool isLowGreaterThanFirstQuarter = _range.Low >= FirstQuarter; bitWriter(isLowGreaterThanFirstQuarter); if (!isLowGreaterThanFirstQuarter) // The alternative defaults missing bits to zero. { ++_scale; // Ensures at least one additional bit is written. EmitE3Mappings(bitWriter, true); // These will default to false for the other case. } Reset(); }
/// <summary> /// Writes the code for <paramref name="symbol" />. If the symbol was not previously encountered, /// the bit sequence to mark a symbol literal is written to <paramref name="bitWriter" /> /// and the symbol through <paramref name="symbolWriter" />. /// </summary> public void WriteCode(TSymbolType symbol, WriteBitDelegate bitWriter, WriteSymbolDelegate <TSymbolType> symbolWriter) { var nytSeen = false; if (HasSymbol(symbol)) { WriteCodeInternal(symbol, bitWriter); } else { WriteCodeInternal(SymbolSpace.NotYetTransmitted, bitWriter); UpdateSymbolInternal(SymbolSpace.NotYetTransmitted, GetTweak(symbol, true)); symbolWriter(symbol); nytSeen = true; } UpdateSymbolInternal(symbol, 1); if (!nytSeen) { UpdateSymbolInternal(SymbolSpace.NotYetTransmitted, GetTweak(symbol, false)); } }
/// <summary> /// Converts writing <paramref name="symbol" /> to writing based on its corresponding index in the tree. /// </summary> private void WriteCodeInternal(SymbolSpace symbol, WriteBitDelegate bitWriter) { WriteCode(_map[symbol], bitWriter); }
// total < 2^29 /// <summary> /// Encodes the range updating the state of the encoder. /// </summary> public void Encode(Range counts, uint total, WriteBitDelegate bitWriter) { if (total >= RangeLimit) { throw new ArgumentOutOfRangeException("total"); } if (counts.Low >= RangeLimit || counts.High >= RangeLimit) { throw new ArgumentOutOfRangeException("counts"); } if (counts.Low >= counts.High) { throw new ArgumentException("counts"); } if (bitWriter == null) { throw new ArgumentNullException("bitWriter"); } // partition number space into single steps _step = (_range.Length())/total; // interval open at the top => +1 // Update bounds -- interval open at the top => -1 for High. _range = (counts*_step + _range.Low) - BoundaryAdjust; // apply e1/e2 mapping while ((_range.High < Half) || (_range.Low >= Half)) { bool isHighLessThanHalf = _range.High < Half; // true => emit false for lower half. uint sub = isHighLessThanHalf ? 0 : Half; bitWriter(!isHighLessThanHalf); EmitE3Mappings(bitWriter, isHighLessThanHalf); _range = (_range - sub)*2 + BoundaryAdjust; } // e3 while (_range.In(FirstQuarter, ThirdQuarter)) { // keep necessary e3 mappings in mind _scale++; _range = (_range - FirstQuarter)*2 + BoundaryAdjust; } }