///|
/// Decode floor type 1 for a single channel.
/// Returns the floor curve as an array of float values, or None if "unused".
fn decode_floor1(
br : BitReader,
floor : VorbisFloorConfig,
codebooks : Array[VorbisCodebook],
n : Int,
) -> Array[Float]? raise AudioError {
let nonzero = read_bit(br)
if not(nonzero) {
return None
}
let range_vals = [256, 128, 86, 64]
let range = range_vals[floor.multiplier - 1]
let y_list : Array[Int] = Array::make(floor.x_list.length(), 0)
// Read floor1 Y values
y_list[0] = read_bits(br, ilog(range - 1))
y_list[1] = read_bits(br, ilog(range - 1))
let mut offset = 2
for i in 0.. 0 {
let master = floor.class_masterbooks[cls]
if master < codebooks.length() {
csub = codebook_decode(codebooks[master], br)
}
}
for j in 0.. 0 {
floor.subclass_books[cls][(csub >> (j * sub)) & ((1 << sub) - 1)]
} else {
floor.subclass_books[cls][0]
}
if book_idx >= 0 && book_idx < codebooks.length() {
y_list[offset] = codebook_decode(codebooks[book_idx], br)
}
offset = offset + 1
}
}
// Synthesize floor curve
let curve = synthesize_floor1_curve(floor, y_list, n, range)
Some(curve)
}
///|
/// Synthesize floor type 1 curve from decoded Y values.
fn synthesize_floor1_curve(
floor : VorbisFloorConfig,
y_list : Array[Int],
n : Int,
range : Int,
) -> Array[Float] {
let result : Array[Float] = Array::make(n, (0.0 : Float))
let num_points = floor.x_list.length()
if num_points < 2 {
return result
}
// Use sorted indices for interpolation
let sorted = floor.sorted_index
// Amplitude rendering
let mut lx = 0
let mut ly = y_list[sorted[0]] * floor.multiplier
for i in 1.. Unit {
let dx = x1 - x0
let dy = y1 - y0
let adx = if dx >= 0 { dx } else { -dx }
let ady = if dy >= 0 { dy } else { -dy }
let base = dy / adx
let sy = if dy < 0 { base - 1 } else { base + 1 }
let mut x = x0
let mut y = y0
let mut err = 0
let x_end = if x1 < n { x1 } else { n }
while x < x_end {
if x >= 0 && x < n {
output[x] = floor1_inverse_db(y)
}
err = err + ady
if err >= adx {
err = err - adx
y = y + sy
} else {
y = y + base
}
x = x + 1
}
}
///|
/// Inverse dB lookup for floor1 values.
/// Simplified: maps integer floor values to linear amplitude.
fn floor1_inverse_db(val : Int) -> Float {
if val <= 0 {
return 0.0
}
// Simplified inverse dB table approximation
// Full Vorbis spec has a 256-entry lookup table
// We approximate: amplitude = 10^((val - 256) * 0.05 / 20)
let db = Float::from_int(val - 256)
let factor = db * (0.05 : Float) / (20.0 : Float)
let ln10 : Float = 2.302585
exp_approx(factor * ln10)
}
///|
/// Approximate exp(x) using Taylor series.
fn exp_approx(x : Float) -> Float {
let mut result : Float = 1.0
let mut term : Float = 1.0
for i in 1..<=20 {
term = term * x / Float::from_int(i)
result = result + term
}
if result < 0.0 {
0.0
} else {
result
}
}