code wiki / (root) / nx_bitio.nx

nx_bitio.nx source

↩ module page · 51 lines · 2047 B

1// nx_bitio.nx -- MSB-first bit-level writer/reader over a byte buffer. 2// 3// Reusable across every sub-byte-coded codec: ACELP pulse-position/sign 4// indices, VQ/RVQ codebook indices, packed gain indices, entropy fields. 5// The voice/video codecs currently pack in whole bytes or nibbles, which 6// wastes bits at low bitrate -- this lets a field be exactly as wide as it 7// needs (e.g. a 17-bit G.729 fixed-codebook index, a 7-bit pitch lag). 8// 9// Functional / positional: the caller owns the bit cursor (so one function 10// can return the value while the caller advances by the known width). The 11// writer tolerates a DIRTY buffer (it both sets and clears each touched 12// bit), so callers need not pre-zero. Big-endian bit order within the 13// stream (MSB of the field emitted first) -- matches ITU/3GPP bit packing. 14// 15// genealogy_id: itu_g729_bitstream + 3gpp_amr_packing 16// lineage_id: nishi_bitio_msb 17 18// Write the low `nbits` bits of `value`, MSB-first, starting at `bitpos`. 19// Returns the new bit cursor (bitpos + nbits). 20func nx_bw_put(buf: *u8, bitpos: i64, value: i64, nbits: i64) -> i64 { 21 var k: i64 = 0 22 while k < nbits { 23 let bit: i64 = (value >> (nbits - 1 - k)) & 1 24 let bp: i64 = bitpos + k 25 let byte: i64 = bp >> 3 26 let off: i64 = 7 - (bp & 7) 27 if bit != 0 { buf[byte] = buf[byte] | (1 << off) } 28 else { buf[byte] = buf[byte] & (255 - (1 << off)) } 29 k = k + 1 30 } 31 return bitpos + nbits 32} 33 34// Read `nbits` bits, MSB-first, starting at `bitpos`. Returns the value 35// (unsigned). The caller advances its cursor by nbits. 36func nx_br_get(buf: *u8, bitpos: i64, nbits: i64) -> i64 { 37 var v: i64 = 0 38 var k: i64 = 0 39 while k < nbits { 40 let bp: i64 = bitpos + k 41 let byte: i64 = bp >> 3 42 let off: i64 = 7 - (bp & 7) 43 let bit: i64 = (buf[byte] >> off) & 1 44 v = (v << 1) | bit 45 k = k + 1 46 } 47 return v 48} 49 50// Bytes needed to hold `bits` bits (rounds up). 51func nx_bits_bytes(bits: i64) -> i64 { return (bits + 7) >> 3 }