// residue.mbt
//
// Vorbis residue setup 解析。
//
// residue 是 floor 与最终频域系数之间的残差,用 codebook 对系数分区编码。
// 三种类型:type 0(interleaved,≤8 通道)、type 1(interleaved,≤256 通道)、
// type 2(non-interleaved)。本阶段解析 setup 配置,实际解码在音频 packet 阶段。
///|
/// residue 的配置。
///
/// * `begin` / `end` : 作用的系数范围(end 是开区间上限);
/// * `partition_size` : 每个 partition 的系数数量;
/// * `classifications` / `classbook` : 分区分类与对应 codebook;
/// * `cascade` : 每个 classification 的残差级联编码描述。
pub struct Residue {
residue_type : Int
begin : Int
end : Int
partition_size : Int
classifications : Int
classbook : Int
cascade : Array[Int]
residue_books : Array[Array[Int]]
}
///|
/// 从 `br` 的当前位置解析一个 residue 配置。
pub fn Residue::parse(br : BitReader) -> Result[Residue, String] {
let residue_type = br.read_bits(16)
if residue_type > 2 {
return Err("invalid residue type")
}
let begin = br.read_bits(24)
let end = br.read_bits(24)
let partition_size = br.read_bits(24) + 1
let classifications = br.read_bits(6) + 1
let classbook = br.read_bits(8)
// 每个 classification 的级联编码
let cascade : Array[Int] = []
for _ in 0.. Result[Unit, String] {
let rtype = self.residue_type
let classbook = codebooks[self.classbook]
let classwords = classbook.dimensions
let ch = targets.length()
let actual_size = if rtype == 2 { n * 2 } else { n }
let limit_begin = if self.begin < actual_size {
self.begin
} else {
actual_size
}
let limit_end = if self.end < actual_size { self.end } else { actual_size }
let n_read = limit_end - limit_begin
let part_read = n_read / self.partition_size
let clear_len = if ch > 1 { n } else { actual_size }
for c in 0.. 1
for pass in 0..<8 {
let mut pcount = 0
while pcount < part_read {
if pass == 0 {
if interleaved {
let temp = match classbook.decode_scalar(br) {
Ok(t) => t
Err(e) => return Err(e)
}
spread_classification(
class_of[0],
pcount,
classwords,
temp,
self.classifications,
)
} else {
for j in 0.. t
Err(e) => return Err(e)
}
spread_classification(
class_of[j],
pcount,
classwords,
temp,
self.classifications,
)
}
}
}
let mut i = 0
while i < classwords && pcount < part_read {
if interleaved {
// type 2 多声道:VQ 系数按声道交错分配
let c = class_of[0][pcount]
let b = self.residue_books[c][pass]
if b >= 0 {
let book = codebooks[b]
let z = limit_begin + pcount * self.partition_size
let mut c_inter = z % ch
let mut p_inter = z / ch
let mut k = 0
while k < self.partition_size {
let entry = match book.decode_scalar(br) {
Ok(e) => e
Err(err) => return Err(err)
}
let dim = book.dimensions
let base = entry * dim
let nn = if dim < self.partition_size - k {
dim
} else {
self.partition_size - k
}
for ii in 0..= 0 {
match
decode_partition(
codebooks[b],
br,
targets[j],
offset,
self.partition_size,
rtype,
) {
Ok(_) => ()
Err(e) => return Err(e)
}
}
}
}
pcount += 1
i += 1
}
}
}
Ok(())
}
///|
/// 把一个 classbook 码字按 classification 数展开成 classwords 个数字,
/// 写在 row 的 pcount 起、由高到低的位置上。
fn spread_classification(
row : Array[Int],
pcount : Int,
classwords : Int,
codeword : Int,
count : Int,
) -> Unit {
let mut q = codeword
let mut k = 0
while k < classwords {
row[pcount + classwords - 1 - k] = q % count
q = q / count
k += 1
}
}
///|
/// 解码一个 partition,把结果累加进 target。
///
/// type 0 是交织写法:每个码字的分量按下标步进而非相邻地摆放,step 个码字
/// 交错铺满整个 partition。type 1 及单声道 type 2 则是顺序摆放。
fn decode_partition(
book : Codebook,
br : BitReader,
target : Array[Float],
offset : Int,
part_size : Int,
rtype : Int,
) -> Result[Unit, String] {
if book.dimensions <= 0 {
return Err("codebook dimensions is zero")
}
if rtype == 0 {
let step = part_size / book.dimensions
for k in 0.. ()
Err(e) => return Err(e)
}
}
} else {
let mut k = 0
while k < part_size {
match book.decode_vq(br, target, offset + k, part_size - k) {
Ok(_) => ()
Err(e) => return Err(e)
}
k += book.dimensions
}
}
Ok(())
}