entcode

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2026 License: BSD-2-Clause Imports: 1 Imported by: 0

Documentation

Overview

Package entcode provides entropy coding (range coding) for Opus, bit-exact with the range coder in libopus 1.3.1 (celt/entcode.c, celt/entenc.c, celt/entdec.c).

Index

Constants

View Source
const (
	// EC_SYM_BITS: number of bits per symbol output.
	SymBits = 8

	// EC_CODE_BITS: total bits in the code register.
	CodeBits = 32

	// EC_SYM_MAX: (1<<EC_SYM_BITS)-1 = 255.
	SymMax = (1 << SymBits) - 1

	// EC_CODE_SHIFT: EC_CODE_BITS - EC_SYM_BITS - 1 = 23.
	CodeShift = CodeBits - SymBits - 1

	// EC_CODE_TOP: 1<<(EC_CODE_BITS-1) = 0x80000000.
	CodeTop = uint32(1 << (CodeBits - 1))

	// EC_CODE_BOT: EC_CODE_TOP >> EC_SYM_BITS = 0x00800000.
	CodeBot = CodeTop >> SymBits

	// EC_CODE_EXTRA: (EC_CODE_BITS-2)%EC_SYM_BITS+1 = 7.
	CodeExtra = (CodeBits-2)%SymBits + 1

	// EC_UINT_BITS: number of bits for the high part of ec_enc_uint.
	UintBits = 8
)

Range coding constants matching libopus.

Variables

This section is empty.

Functions

func ILog

func ILog(val uint32) int

ILog returns the number of bits needed to represent val (floor(log2(val))+1). Returns 0 for val == 0. Matches libopus EC_ILOG.

func Log2Ceiling

func Log2Ceiling(n int) int

Log2Ceiling computes ceil(log2(n)).

Types

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder is a range decoder bit-exact with libopus ec_dec (celt/entdec.c).

libopus uses a TOP-DOWN convention:

  • rng: current range
  • dif: difference = (top of range) - (coded value)
  • rem: remainder from byte-unpacking (EC_CODE_EXTRA bits)

The decoder reads bytes and combines them using the EC_CODE_EXTRA (7-bit) overlap scheme from libopus.

func NewDecoder

func NewDecoder(data []byte) *Decoder

NewDecoder creates a new range decoder from encoded data. Matches ec_dec_init in libopus.

func (*Decoder) AdvanceTellTo

func (dec *Decoder) AdvanceTellTo(bits int)

AdvanceTellTo pretends that bits have been consumed up to the supplied libopus ec_tell position without changing the range. CELT uses this for packets carrying the silence flag.

func (*Decoder) BytesLeft

func (dec *Decoder) BytesLeft() int

BytesLeft returns remaining unread bytes.

func (*Decoder) Decode

func (dec *Decoder) Decode(ft uint32) uint32

Decode returns the CDF position for a symbol from [0, ft). Must be followed by DecodeUpdate. Matches ec_decode in libopus.

In top-down convention, dif/r gives position from top.

func (*Decoder) DecodeBit

func (dec *Decoder) DecodeBit(prob uint16) bool

DecodeBit decodes a single bit. prob is probability of false on 0-32768 scale. Matches the custom EncodeBit in encoder.go (not a libopus API).

Encoder: split = rng - (rng >> 15) * prob

true:  val += split, rng -= split  (true at top in val-space)
false: rng = split                  (false at bottom in val-space)

Top-down: true => dif in [0, rng-split), false => dif in [rng-split, rng) rng - split = (rng >> 15) * prob

func (*Decoder) DecodeBitLogp

func (dec *Decoder) DecodeBitLogp(logp uint) bool

DecodeBitLogp decodes a single bit with probability 1/(1<<logp) of being 1. Matches ec_dec_bit_logp in libopus.

Encoder convention (ec_enc_bit_logp):

r = rng >> logp
if bit: val += rng - r; rng = r   (true at top, width r)
else:   rng -= r                    (false at bottom, width rng-r)

Top-down decoder: dif < r => true, dif >= r => false.

func (*Decoder) DecodeBits

func (dec *Decoder) DecodeBits(nbits uint) uint32

DecodeBits decodes raw bits from the end of the packet, matching ec_dec_bits.

func (*Decoder) DecodeGetCumu

func (dec *Decoder) DecodeGetCumu(ft uint32) uint32

DecodeGetCumu returns the cumulative frequency position of the current symbol in [0, ft). This is equivalent to Decode but named for use with explicit-frequency protocols such as recursive PVQ splitting.

func (*Decoder) DecodeIcdf

func (dec *Decoder) DecodeIcdf(icdf []uint8, ftb int) int

DecodeIcdf decodes a symbol from a descending ICDF table with ft = 1<<ftb. Bit-exact with ec_dec_icdf in libopus.

The libopus algorithm iterates through icdf entries:

s = rng; d = dif; r = rng >> ftb; ret = -1;
do { t = s; s = r * icdf[++ret]; } while (d < s);
dif = d - s; rng = t - s; normalize();

func (*Decoder) DecodeLaplace

func (dec *Decoder) DecodeLaplace(fs uint32, decay int) int

DecodeLaplace decodes an integer value assumed to be Laplace-distributed.

fs is Pr(X==0)×32768; decay is the per-step decay×32768.

Matches ec_laplace_decode in libopus celt/laplace.c.

func (*Decoder) DecodeUint

func (dec *Decoder) DecodeUint(ft uint32) uint32

DecodeUint decodes a value in [0, ft) using ec_dec_uint scheme from libopus.

func (*Decoder) DecodeUintTrace

func (dec *Decoder) DecodeUintTrace(ft uint32) uint32

DecodeUintTrace is a debug version of DecodeUint that prints intermediate steps.

func (*Decoder) DecodeUpdate

func (dec *Decoder) DecodeUpdate(fl, fh, ft uint32)

DecodeUpdate updates decoder state after Decode. fl, fh are CDF bounds [fl, fh) out of [0, ft). Matches ec_dec_update in libopus.

func (*Decoder) ECTell

func (dec *Decoder) ECTell() int

ECTell returns bits consumed using the libopus ec_tell convention (== 1 immediately after init). Our internal Tell() reports ec_tell-1, so this is simply Tell()+1. Use this where porting libopus guards verbatim.

func (*Decoder) Error

func (dec *Decoder) Error() error

Error returns any decoding error.

func (*Decoder) GetDif

func (dec *Decoder) GetDif() uint32

Debug accessors for testing

func (*Decoder) GetEndOffs

func (dec *Decoder) GetEndOffs() int

func (*Decoder) GetNendBits

func (dec *Decoder) GetNendBits() uint

func (*Decoder) GetPos

func (dec *Decoder) GetPos() int

func (*Decoder) GetRem

func (dec *Decoder) GetRem() int

func (*Decoder) GetRng

func (dec *Decoder) GetRng() uint32

func (*Decoder) ShrinkStorage

func (dec *Decoder) ShrinkStorage(n int)

ShrinkStorage reduces the decoder's effective buffer length by n bytes, matching libopus `dec->storage -= n`. Raw bits (DecodeBits) are read from the end of the buffer, so shrinking storage keeps the main range decoder from reading into trailing bytes reserved for a redundant frame. Forward range reads (pos) are unaffected as long as they have not yet reached the new end.

func (*Decoder) Tell

func (dec *Decoder) Tell() int

Tell returns the number of bits consumed so far. Matches ec_tell: bits from start (range coder) + bits consumed from end (raw).

func (*Decoder) TellFrac

func (dec *Decoder) TellFrac() int

TellFrac returns bits consumed in 1/8-bit (Q3) resolution. Bit-exact with ec_tell_frac in libopus (celt/entcode.c).

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder is a range encoder bit-exact with libopus ec_enc (celt/entenc.c).

State uses the carry-propagation scheme from libopus:

  • val (uint32): 31-bit accumulator (values in [0, CodeTop))
  • rng (uint32): current range, always in (CodeBot, CodeTop] after normalize
  • rem (int): pending output byte (-1 = empty)
  • ext (uint32): count of pending 0xFF bytes (carry chain)
  • buf ([]byte): output buffer

func NewEncoder

func NewEncoder(capacity int) *Encoder

NewEncoder creates a new range encoder. capacity is the intended packet size in bytes; it sets where end-of-packet raw bits are placed (the absolute end).

func (*Encoder) Bytes

func (enc *Encoder) Bytes() []byte

Bytes returns the encoded packet. Call Flush first.

When no raw end-of-packet bits were written, this returns the minimal range- coded front buffer (preserving the historical byte-length semantics relied on by size-measuring tests). When raw bits exist, it assembles the libopus-style layout: forward range bytes at the front, a zeroed gap, and the raw bytes at the absolute end (so the decoder's DecodeBits reads them from the end). The packet is sized to capacity when that leaves room, matching a fixed-size Opus payload; otherwise it grows to fit.

func (*Encoder) ECTell added in v1.1.0

func (enc *Encoder) ECTell() int

ECTell returns bits consumed using the libopus ec_tell convention (== 1 immediately after init). Our internal Tell() reports ec_tell-1, so this is Tell()+1, matching the decoder's ECTell(). Use this where porting libopus guards verbatim so encoder and decoder budget decisions stay symmetric.

func (*Encoder) Encode

func (enc *Encoder) Encode(fl, fh, ft uint32)

Encode encodes a symbol in [fl, fh) out of [0, ft). Uses the same CDF-mapping convention as DecodeIcdf/Decode: symbol at CDF [fl, fh) maps to sub-range [r*fl, r*fh) with remainder going to the fl=0 (bottom) symbol.

func (*Encoder) EncodeBit

func (enc *Encoder) EncodeBit(bit bool, prob uint16)

EncodeBit encodes a single bit. prob is probability of false on a 0-32768 scale.

func (*Encoder) EncodeBitLogp

func (enc *Encoder) EncodeBitLogp(bit bool, logp uint)

EncodeBitLogp encodes a single bit with probability 1/(1<<logp) of being 1. Matches ec_enc_bit_logp in libopus.

func (*Encoder) EncodeBits

func (enc *Encoder) EncodeBits(fl uint32, nbits uint)

EncodeBits writes nbits raw bits to the END of the packet, LSB first. Bit-exact with libopus ec_enc_bits (celt/entenc.c): symmetric with the decoder's DecodeBits, which reads raw bits from the end of the packet.

func (*Encoder) EncodeExact

func (enc *Encoder) EncodeExact(fl, fh, ft uint32)

EncodeExact encodes a symbol given its exact cumulative frequency range. fl: cumulative frequency of symbols < symbol fh: cumulative frequency of symbols <= symbol ft: total frequency (may be non-power-of-2)

func (*Encoder) EncodeIcdf

func (enc *Encoder) EncodeIcdf(symbol int, icdf []uint8, ftb int)

EncodeIcdf encodes a symbol using a descending ICDF table with ft = 1<<ftb. icdf[s] = ft - CDF(s+1), last entry must be 0. Bit-exact with ec_enc_icdf in libopus.

func (*Encoder) EncodeLaplace

func (enc *Encoder) EncodeLaplace(value *int, fs uint32, decay int)

EncodeLaplace encodes an integer value assumed to be Laplace-distributed.

value is passed by pointer; it may be clamped to the maximum representable value if the range coder runs out of precision, matching libopus behaviour.

fs is Pr(X==0)×32768; decay is the per-step decay×32768.

Matches ec_laplace_encode in libopus celt/laplace.c.

func (*Encoder) EncodeUint

func (enc *Encoder) EncodeUint(val, ft uint32)

EncodeUint encodes val in [0, ft) using the ec_enc_uint scheme from libopus.

func (*Encoder) Flush

func (enc *Encoder) Flush()

Flush finalizes encoding. Must be called before Bytes().

The libopus ec_enc_done operates on a fixed-size pre-allocated buffer. Our encoder uses a dynamic buffer, so we directly compute the byte sequence that the decoder's init + normalize will reconstruct as a value within the final [val, val+rng) interval.

func (*Encoder) GetExt

func (enc *Encoder) GetExt() uint32

func (*Encoder) GetRem

func (enc *Encoder) GetRem() int

func (*Encoder) GetRng

func (enc *Encoder) GetRng() uint32

func (*Encoder) GetVal

func (enc *Encoder) GetVal() uint32

Debug accessors for testing

func (*Encoder) Shrink added in v1.1.0

func (enc *Encoder) Shrink(newSize int)

Shrink reduces the encoder's capacity (storage) to newSize bytes. This is the equivalent of libopus ec_enc_shrink: for VBR mode, after encoding all symbols, the packet can be shrunk so that the decoder sees a smaller packet and computes its allocation accordingly. The raw end-of-packet bits are logically relocated to the new end position.

In libopus the raw tail bytes must be memmove'd because they live at the end of a single flat buffer. Our encoder keeps endBytes in a separate slice, so only the capacity field needs updating — Bytes() already places the tail at offset capacity-1.

Precondition: newSize >= len(buf) + len(endBytes) (the range-coded front and raw tail must both fit).

func (*Encoder) Tell

func (enc *Encoder) Tell() int

Tell returns the number of bits used so far, including end-of-packet raw bits (mirrors libopus ec_tell, whose nbits_total counts raw bits via ec_enc_bits).

func (*Encoder) TellFrac added in v1.1.0

func (enc *Encoder) TellFrac() int

TellFrac returns bits used in 1/8-bit (Q3) resolution, bit-exact with ec_tell_frac in libopus (celt/entcode.c). Symmetric with Decoder.TellFrac so the shared CELT quant/allocation code computes identical budgets in both directions.

func (*Encoder) UsedBytes added in v1.1.0

func (enc *Encoder) UsedBytes() int

UsedBytes returns the minimum number of bytes needed to hold the encoded content. Valid after Flush(). This mirrors (ec_tell(&enc)+7)/8 in libopus which is used to determine the shrink target for VBR packets.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL