pub(super) struct MelDecoder<'a> {
data: &'a [u8],
pos: usize,
remaining: usize,
unstuff: bool,
current_byte: u8,
bits_left: u8,
k: usize,
num_runs: usize,
runs: u64,
}
impl<'a> MelDecoder<'a> {
pub(super) fn new(data: &'a [u8], lcup: usize, scup: usize) -> Self {
Self {
data,
pos: lcup - scup,
remaining: scup - 1,
unstuff: false,
current_byte: 0,
bits_left: 0,
k: 0,
num_runs: 0,
runs: 0,
}
}
fn read_bit(&mut self) -> Option<u32> {
if self.bits_left == 0 {
let mut byte = if self.remaining > 0 {
let byte = self.data.get(self.pos).copied()?;
self.pos += 1;
self.remaining -= 1;
byte
} else {
0xFF
};
if self.remaining == 0 {
byte |= 0x0F;
}
self.current_byte = byte;
self.bits_left = 8 - u8::from(self.unstuff);
self.unstuff = byte == 0xFF;
}
self.bits_left -= 1;
Some(u32::from((self.current_byte >> self.bits_left) & 1))
}
fn read_bits(&mut self, count: usize) -> Option<u32> {
let mut value = 0;
for _ in 0..count {
value = (value << 1) | self.read_bit()?;
}
Some(value)
}
fn decode_more_runs(&mut self) -> Option<()> {
const MEL_EXP: [usize; 13] = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5];
while self.num_runs < 8 {
let eval = MEL_EXP[self.k];
let first = self.read_bit()?;
let run = if first == 1 {
self.k = (self.k + 1).min(12);
((1usize << eval) - 1) << 1
} else {
self.k = self.k.saturating_sub(1);
(self.read_bits(eval)? as usize) << 1 | 1
};
self.runs |= (run as u64) << (self.num_runs * 7);
self.num_runs += 1;
if eval == 5 && first == 0 && self.num_runs >= 8 {
break;
}
}
Some(())
}
pub(super) fn get_run(&mut self) -> Option<i32> {
if self.num_runs == 0 {
self.decode_more_runs()?;
}
let run = (self.runs & 0x7F) as i32;
self.runs >>= 7;
self.num_runs -= 1;
Some(run)
}
}
#[derive(Clone)]
pub(super) struct ForwardBitReader<'a, const PAD: u8> {
data: &'a [u8],
pos: usize,
tmp: u64,
bits: u32,
unstuff: bool,
}
impl<'a, const PAD: u8> ForwardBitReader<'a, PAD> {
pub(super) fn new(data: &'a [u8]) -> Self {
Self {
data,
pos: 0,
tmp: 0,
bits: 0,
unstuff: false,
}
}
#[expect(clippy::inline_always, reason = "per-sample refill check")]
#[inline(always)]
fn fill(&mut self) {
if !self.unstuff && self.bits > 0 {
if let Some(&[b0, b1, b2, b3]) = self.data.get(self.pos..self.pos + 4) {
let word = u32::from_le_bytes([b0, b1, b2, b3]);
if b0 != 0xFF && b1 != 0xFF && b2 != 0xFF {
self.tmp |= u64::from(word) << self.bits;
self.bits += 32;
self.pos += 4;
self.unstuff = b3 == 0xFF;
return;
}
}
}
*self = self.clone().fill_bytes();
}
#[cold]
#[inline(never)]
fn fill_bytes(mut self) -> Self {
while self.bits <= 32 {
let byte = if self.pos < self.data.len() {
let byte = self.data[self.pos];
self.pos += 1;
byte
} else {
PAD
};
let valid_bits = 8 - u32::from(self.unstuff);
let next_unstuff = byte == 0xFF;
let byte = if self.unstuff { byte & 0x7F } else { byte };
self.tmp |= u64::from(byte) << self.bits;
self.bits += valid_bits;
self.unstuff = next_unstuff;
}
self
}
#[expect(clippy::cast_possible_truncation, reason = "low reservoir word")]
pub(super) fn fetch(&mut self) -> u32 {
if self.bits < 32 {
self.fill();
}
self.tmp as u32
}
pub(super) fn advance(&mut self, count: u32) {
debug_assert!(count <= self.bits);
self.tmp >>= count;
self.bits -= count;
}
}
#[derive(Clone)]
pub(super) struct ReverseBitReader<'a> {
data: &'a [u8],
pos: isize,
remaining: usize,
tmp: u64,
bits: u32,
unstuff: bool,
}
impl<'a> ReverseBitReader<'a> {
#[expect(clippy::cast_possible_wrap, reason = "validated signed cursor")]
pub(super) fn new_vlc(data: &'a [u8], lcup: usize, scup: usize) -> Self {
let d = data[lcup - 2];
let tmp = u64::from(d >> 4);
let bits = 4 - u32::from((tmp & 0x7) == 0x7);
Self {
data,
pos: lcup as isize - 3,
remaining: scup - 2,
tmp,
bits,
unstuff: d > 0x8F,
}
}
#[expect(clippy::cast_possible_wrap, reason = "validated signed cursor")]
pub(super) fn new_mrp(data: &'a [u8]) -> Self {
Self {
data,
pos: data.len() as isize - 1,
remaining: data.len(),
tmp: 0,
bits: 0,
unstuff: true,
}
}
#[expect(
clippy::cast_sign_loss,
clippy::inline_always,
reason = "nonnegative live cursor; per-quad refill check"
)]
#[inline(always)]
fn fill(&mut self) {
if self.bits > 0 && self.remaining >= 4 && self.pos >= 3 {
let last = self.pos as usize;
if let Some(&[b3, b2, b1, b0]) = self.data.get(last - 3..=last) {
let word = u32::from_le_bytes([b0, b1, b2, b3]);
let above_8f = word & 0x8080_8080 & ((word & 0x7070_7070) + 0x7070_7070);
let low_ones = ((word & 0x7F7F_7F7F) + 0x0101_0101) & 0x8080_8080;
let after_above_8f = (above_8f << 8) | (u32::from(self.unstuff) << 7);
if after_above_8f & low_ones == 0 {
self.tmp |= u64::from(word) << self.bits;
self.bits += 32;
self.pos -= 4;
self.remaining -= 4;
self.unstuff = above_8f >> 31 != 0;
return;
}
}
}
*self = self.clone().fill_bytes();
}
#[expect(clippy::cast_sign_loss, reason = "nonnegative live cursor")]
#[cold]
#[inline(never)]
fn fill_bytes(mut self) -> Self {
while self.bits <= 32 {
let byte = if self.remaining > 0 {
let byte = self.data[self.pos as usize];
self.pos -= 1;
self.remaining -= 1;
byte
} else {
0
};
let stuffed = self.unstuff && (byte & 0x7F) == 0x7F;
let d_bits = 8 - u32::from(stuffed);
let next_unstuff = byte > 0x8F;
let byte = if stuffed { byte & 0x7F } else { byte };
self.tmp |= u64::from(byte) << self.bits;
self.bits += d_bits;
self.unstuff = next_unstuff;
}
self
}
#[expect(clippy::cast_possible_truncation, reason = "low reservoir word")]
pub(super) fn fetch(&mut self) -> u32 {
if self.bits < 32 {
self.fill();
}
self.tmp as u32
}
#[expect(clippy::cast_possible_truncation, reason = "low reservoir word")]
pub(super) fn advance(&mut self, count: u32) -> u32 {
debug_assert!(count <= self.bits);
self.tmp >>= count;
self.bits -= count;
self.tmp as u32
}
}
#[expect(clippy::inline_always, reason = "inline two loads in refinement scans")]
#[inline(always)]
pub(super) fn read_u32_pair(values: &[u16], index: usize) -> u32 {
u32::from(values[index]) | (u32::from(values[index + 1]) << 16)
}
#[cfg(test)]
mod tests;