Skip to main content

libflo_audio/lossy/
decoder.rs

1use super::encoder::TransformFrame;
2use super::mdct::{BlockSize, Mdct, WindowType, LONG_BLOCK_SIZE, SHORT_BLOCK_SIZE};
3use super::psychoacoustic::{PsychoacousticModel, NUM_BARK_BANDS};
4use alloc::vec;
5use alloc::vec::Vec;
6
7/// Transform lossy decoder
8pub struct TransformDecoder {
9    /// Sample rate
10    sample_rate: u32,
11    /// Number of channels
12    channels: u8,
13    /// MDCT processor
14    mdct: Mdct,
15}
16
17impl TransformDecoder {
18    /// Create a new transform decoder
19    pub fn new(sample_rate: u32, channels: u8) -> Self {
20        let mdct = Mdct::new(channels as usize, WindowType::Vorbis);
21
22        Self {
23            sample_rate,
24            channels,
25            mdct,
26        }
27    }
28
29    /// Decode a frame
30    /// Returns interleaved samples
31    pub fn decode_frame(&mut self, frame: &TransformFrame) -> Vec<f32> {
32        if frame.block_size.is_short_group() {
33            // A short group carries SHORTS_PER_GROUP windows of 128 coefficients
34            // each at 256-sample frequency resolution.
35            let freq_resolution = self.sample_rate as f32 / SHORT_BLOCK_SIZE as f32;
36            let coeffs_per_window = SHORT_BLOCK_SIZE / 2;
37            self.decode_frame_inner(frame, coeffs_per_window, freq_resolution)
38        } else {
39            let freq_resolution = self.sample_rate as f32 / LONG_BLOCK_SIZE as f32;
40            let coeffs_per_window = LONG_BLOCK_SIZE / 2;
41            self.decode_frame_inner(frame, coeffs_per_window, freq_resolution)
42        }
43    }
44
45    /// Dequantize and synthesize a frame with the given coefficient-to-frequency mapping
46    fn decode_frame_inner(
47        &mut self,
48        frame: &TransformFrame,
49        coeffs_per_window: usize,
50        freq_resolution: f32,
51    ) -> Vec<f32> {
52        // Dequantize coefficients
53        let mut dequantized: Vec<Vec<f32>> = Vec::with_capacity(self.channels as usize);
54
55        for (ch, quantized) in frame.coefficients.iter().enumerate() {
56            let mut coeffs = vec![0.0f32; quantized.len()];
57
58            for (k, (&q, c)) in quantized.iter().zip(coeffs.iter_mut()).enumerate() {
59                let bin = k % coeffs_per_window;
60                let freq = (bin as f32 + 0.5) * freq_resolution;
61                let band = PsychoacousticModel::freq_to_bark_band(freq);
62
63                if frame.scale_factors[ch][band] > 0.0 {
64                    *c = q as f32 / frame.scale_factors[ch][band];
65                }
66            }
67
68            dequantized.push(coeffs);
69        }
70
71        // IMDCT + overlap-add
72        self.mdct.synthesize(&dequantized, frame.block_size)
73    }
74
75    /// Reset decoder state
76    pub fn reset(&mut self) {
77        self.mdct.reset();
78    }
79}
80
81/// Deserialize a transform frame from bytes
82pub fn deserialize_frame(data: &[u8]) -> Option<TransformFrame> {
83    if data.len() < 2 {
84        return None;
85    }
86
87    let mut pos = 0;
88
89    // Block size
90    let block_size = match data[pos] {
91        0 => BlockSize::Long,
92        1 => BlockSize::Short,
93        2 => BlockSize::Start,
94        3 => BlockSize::Stop,
95        _ => return None,
96    };
97    pos += 1;
98
99    // Derive num_coeffs from block size
100    let num_coeffs = block_size.frame_coefficients();
101
102    // Number of channels
103    let num_channels = data[pos] as usize;
104    pos += 1;
105
106    // Scale factors (stored as log-scale u16)
107    let mut scale_factors = Vec::with_capacity(num_channels);
108    for _ in 0..num_channels {
109        let mut sf = vec![0.0f32; NUM_BARK_BANDS];
110        for s in &mut sf {
111            if pos + 2 > data.len() {
112                return None;
113            }
114            let log_sf = u16::from_le_bytes(data[pos..pos + 2].try_into().ok()?);
115            pos += 2;
116
117            // Decode from log scale: 2^((log_sf - 32768) / 256)
118            if log_sf > 0 {
119                *s = libm::powf(2.0f32, (log_sf as f32 - 32768.0) / 256.0);
120            }
121        }
122        scale_factors.push(sf);
123    }
124
125    // Coefficients (sparse encoded)
126    let mut coefficients = Vec::with_capacity(num_channels);
127    for _ in 0..num_channels {
128        // Length (4 bytes)
129        if pos + 4 > data.len() {
130            return None;
131        }
132        let len = u32::from_le_bytes(data[pos..pos + 4].try_into().ok()?) as usize;
133        pos += 4;
134
135        if pos + len > data.len() {
136            return None;
137        }
138
139        // Sparse decode
140        let quantized = deserialize_sparse(&data[pos..pos + len], num_coeffs);
141        coefficients.push(quantized);
142
143        pos += len;
144    }
145
146    Some(TransformFrame {
147        coefficients,
148        scale_factors,
149        block_size,
150        num_samples: block_size.frame_coefficients(),
151    })
152}
153
154/// Decode sparse coefficients
155pub fn deserialize_sparse(data: &[u8], num_coeffs: usize) -> Vec<i16> {
156    let mut output = vec![0i16; num_coeffs];
157    let mut pos = 0;
158    let mut out_idx = 0;
159
160    while pos < data.len() && out_idx < num_coeffs {
161        // Read zero count
162        let (zero_count, bytes_read) = decode_varint(&data[pos..]);
163        pos += bytes_read;
164
165        // Skip zeros
166        out_idx += zero_count as usize;
167
168        if pos >= data.len() {
169            break;
170        }
171
172        // Read non-zero count
173        let non_zero_count = data[pos] as usize;
174        pos += 1;
175
176        // Read non-zero values
177        for _ in 0..non_zero_count {
178            if pos + 2 > data.len() || out_idx >= num_coeffs {
179                break;
180            }
181            output[out_idx] = i16::from_le_bytes([data[pos], data[pos + 1]]);
182            pos += 2;
183            out_idx += 1;
184        }
185    }
186
187    output
188}
189
190/// Decode varint, returns (value, bytes_read)
191fn decode_varint(data: &[u8]) -> (u32, usize) {
192    let mut value = 0u32;
193    let mut shift = 0;
194    let mut bytes_read = 0;
195
196    for &byte in data {
197        value |= ((byte & 0x7F) as u32) << shift;
198        bytes_read += 1;
199        if byte & 0x80 == 0 {
200            break;
201        }
202        shift += 7;
203        if shift >= 32 {
204            break;
205        }
206    }
207
208    (value, bytes_read)
209}