///|
/// Subframe decoding: the per-channel blocks that carry a frame's audio.
///
/// Four subframe types are supported — CONSTANT, VERBATIM, FIXED and LPC.
/// Each starts with an 8-bit header (a zero bit, a 6-bit type code, and a
/// wasted-bits flag) and, for the predictive types, runs a predictor over a
/// Rice-coded residual.
/// Decode one subframe of `block_size` samples at `bits_per_sample` bits per
/// sample, returning the signed samples and the reader past the subframe.
pub fn BitReader::read_subframe(
self : BitReader,
block_size : Int,
bits_per_sample : Int
) -> (Array[Int], BitReader) raise DecodeError {
let (header, r0) = self.read_byte()
if (header & 0x80) != 0 {
raise InvalidSubframe
}
let type_code = (header >> 1) & 0x3F
let mut r = r0
let mut wasted_bits = 0
if (header & 1) == 1 {
let (w, r1) = r.read_unary()
wasted_bits = w + 1
r = r1
}
let bps = bits_per_sample - wasted_bits
if bps < 1 {
raise InvalidSubframe
}
let (raw, r2) = if type_code == 0 {
read_constant(r, block_size, bps)
} else if type_code == 1 {
read_verbatim(r, block_size, bps)
} else if type_code >= 8 && type_code <= 12 {
read_fixed(r, block_size, bps, type_code - 8)
} else if type_code >= 32 {
read_lpc(r, block_size, bps, type_code - 31)
} else {
raise InvalidSubframe
}
if wasted_bits > 0 {
let shifted = Array::make(raw.length(), 0)
for i in 0.. (Array[Int], BitReader) raise DecodeError {
let (v, r2) = r.read_signed(bps)
(Array::make(block_size, v), r2)
}
/// VERBATIM: `block_size` samples stored as-is.
fn read_verbatim(r : BitReader, block_size : Int, bps : Int) -> (Array[Int], BitReader) raise DecodeError {
let samples = Array::make(block_size, 0)
let mut rr = r
for i in 0.. (Array[Int], BitReader) raise DecodeError {
let samples = Array::make(block_size, 0)
let mut rr = r
for i in 0.. (Array[Int], BitReader) raise DecodeError {
let samples = Array::make(block_size, 0)
let mut rr = r
for i in 0.. Unit {
let n = samples.length()
for i in order.. 0
1 => samples[i - 1]
2 => 2 * samples[i - 1] - samples[i - 2]
3 => 3 * samples[i - 1] - 3 * samples[i - 2] + samples[i - 3]
4 => 4 * samples[i - 1] - 6 * samples[i - 2] + 4 * samples[i - 3] - samples[i - 4]
_ => 0
}
samples.set(i, residual[i - order] + pred)
}
}
/// In-place linear-predictor reconstruction. Coefficients are stored in reverse
/// chronological order, so `coeffs[j]` multiplies the sample `j + 1` positions
/// back.
fn restore_lpc(order : Int, shift : Int, coeffs : Array[Int], samples : Array[Int], residual : Array[Int]) -> Unit {
let n = samples.length()
for i in order..> shift
samples.set(i, residual[i - order] + pred)
}
}