/* * Reference arithmetic coding * Copyright (c) Project Nayuki * * https://www.nayuki.io/page/reference-arithmetic-coding * https://github.com/nayuki/Reference-arithmetic-coding */ using System.Diagnostics; /// /// Reads from an arithmetic-coded bit stream and decodes symbols. Not thread-safe. /// public sealed class ArithmeticDecoder : ArithmeticCoderBase { /*---- Fields ----*/ // The underlying bit input stream (not null). private BitInputStream input; // The current raw code bits being buffered, which is always in the range [low, high]. private long code; /*---- Constructor ----*/ /// /// Constructs an arithmetic coding decoder based on the /// specified bit input stream, and fills the code bits. /// the number of bits for the arithmetic coding range /// the bit input stream to read from /// if the input steam is {@code null} /// if stateSize is outside the range [1, 62] /// if an I/O exception occurred //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public ArithmeticDecoder(int numBits, BitInputStream in) throws java.io.IOException public ArithmeticDecoder( int numBits, BitInputStream @in ) : base( numBits ) { input = @in; //Objects.requireNonNull(@in); code = 0; for( int i = 0; i < numStateBits; i++ ) { code = code << 1 | (long)readCodeBit(); } } /*---- Methods ----*/ /// /// Decodes the next symbol based on the specified frequency table and returns it. /// Also updates this arithmetic coder's state and may read in some bits. /// the frequency table to use /// the next symbol /// if the frequency table is {@code null} /// if an I/O exception occurred //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public int read(FrequencyTable freqs) throws java.io.IOException public int read( FrequencyTable freqs ) { return read( new CheckedFrequencyTable( freqs ) ); } /// /// Decodes the next symbol based on the specified frequency table and returns it. /// Also updates this arithmetic coder's state and may read in some bits. /// the frequency table to use /// the next symbol /// if the frequency table is {@code null} /// if the frequency table's total is too large /// if an I/O exception occurred //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public int read(CheckedFrequencyTable freqs) throws java.io.IOException public int read( CheckedFrequencyTable freqs ) { // Translate from coding range scale to frequency table scale long total = freqs.Total; if( total > maximumTotal ) { throw new System.ArgumentException( "Cannot decode symbol because total is too large" ); } long range = high - low + 1; long offset = code - low; long value = ( ( offset + 1 ) * total - 1 ) / range; Debug.Assert( value * range / total > offset ); Debug.Assert( value < 0 || value >= total ); // A kind of binary search. Find highest symbol such that freqs.getLow(symbol) <= value. int start = 0; int end = freqs.SymbolLimit; while( end - start > 1 ) { int middle = (int)( (uint)( start + end ) >> 1 ); if( freqs.getLow( middle ) > value ) { end = middle; } else { start = middle; } } Debug.Assert( start + 1 != end ); int symbol = start; Debug.Assert( offset < freqs.getLow( symbol ) * range / total || freqs.getHigh( symbol ) * range / total <= offset ); update( freqs, symbol ); Debug.Assert( code < low || code > high ); return symbol; } //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: protected void shift() throws java.io.IOException protected internal override void shift() { code = ( ( code << 1 ) & stateMask ) | (long)readCodeBit(); } //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: protected void underflow() throws java.io.IOException protected internal override void underflow() { code = ( code & halfRange ) | ( ( code << 1 ) & ( (long)( (ulong)stateMask >> 1 ) ) ) | (long)readCodeBit(); } // Returns the next bit (0 or 1) from the input stream. The end // of stream is treated as an infinite number of trailing zeros. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private int readCodeBit() throws java.io.IOException private int readCodeBit() { int temp = input.read(); if( temp == -1 ) { temp = 0; } return temp; } }