Skip to main content

libflo_audio/
reader.rs

1use crate::core::{
2    ChannelData, FloFile, FloResult, Frame, FrameType, Header, ResidualEncoding, TocEntry,
3};
4use crate::MAGIC;
5use alloc::vec;
6use alloc::vec::Vec;
7
8/// binary reader for flo format
9pub struct Reader;
10
11impl Reader {
12    /// new reader
13    pub fn new() -> Self {
14        Reader
15    }
16
17    /// read and parse a flo file
18    pub fn read(&self, data: &[u8]) -> FloResult<FloFile> {
19        let mut cursor = Cursor::new(data);
20
21        // magic
22        let magic = cursor.read_bytes(4)?;
23        if magic != MAGIC {
24            return Err("Invalid flo file: bad magic".into());
25        }
26
27        // header
28        let header = self.read_header(&mut cursor)?;
29
30        // toc
31        let toc_size = usize::try_from(header.toc_size)
32            .map_err(|_| crate::core::FloError::from("TOC size does not fit in memory"))?;
33        let data_size = usize::try_from(header.data_size)
34            .map_err(|_| crate::core::FloError::from("DATA size does not fit in memory"))?;
35        let extra_size = usize::try_from(header.extra_size)
36            .map_err(|_| crate::core::FloError::from("EXTRA size does not fit in memory"))?;
37        let meta_size = usize::try_from(header.meta_size)
38            .map_err(|_| crate::core::FloError::from("META size does not fit in memory"))?;
39
40        let toc = self.read_toc(&mut cursor, toc_size)?;
41
42        // Read DATA chunk
43        let frames = self.read_data_chunk(&mut cursor, data_size, header.channels, &toc)?;
44
45        // Skip EXTRA chunk
46        cursor.skip(extra_size)?;
47
48        // Read META chunk
49        let metadata = cursor.read_bytes(meta_size)?;
50
51        Ok(FloFile {
52            header,
53            toc,
54            frames,
55            extra: vec![],
56            metadata,
57        })
58    }
59
60    fn read_header(&self, cursor: &mut Cursor) -> FloResult<Header> {
61        Ok(Header {
62            version_major: cursor.read_u8()?,
63            version_minor: cursor.read_u8()?,
64            flags: cursor.read_u16_le()?,
65            sample_rate: cursor.read_u32_le()?,
66            channels: cursor.read_u8()?,
67            bit_depth: cursor.read_u8()?,
68            total_samples: cursor.read_u64_le()?,
69            compression_level: cursor.read_u8()?,
70            data_crc32: {
71                cursor.skip(3)?; // reserved
72                cursor.read_u32_le()?
73            },
74            header_size: cursor.read_u64_le()?,
75            toc_size: cursor.read_u64_le()?,
76            data_size: cursor.read_u64_le()?,
77            extra_size: cursor.read_u64_le()?,
78            meta_size: cursor.read_u64_le()?,
79        })
80    }
81
82    fn read_toc(&self, cursor: &mut Cursor, toc_size: usize) -> FloResult<Vec<TocEntry>> {
83        if toc_size < 4 {
84            cursor.skip(toc_size)?;
85            return Ok(vec![]);
86        }
87
88        let toc_end = cursor.checked_end(toc_size)?;
89
90        let num_entries = cursor.read_u32_le()? as usize;
91
92        if num_entries > 100_000 {
93            return Err("Invalid TOC: too many entries".into());
94        }
95
96        let mut entries = Vec::with_capacity(num_entries);
97
98        for _ in 0..num_entries {
99            entries.push(TocEntry {
100                frame_index: cursor.read_u32_le()?,
101                byte_offset: cursor.read_u64_le()?,
102                frame_size: cursor.read_u32_le()?,
103                timestamp_ms: cursor.read_u32_le()?,
104            });
105        }
106
107        if cursor.pos > toc_end {
108            return Err("TOC entries exceed TOC size".into());
109        }
110        cursor.pos = toc_end;
111
112        Ok(entries)
113    }
114
115    fn read_data_chunk(
116        &self,
117        cursor: &mut Cursor,
118        data_size: usize,
119        channels: u8,
120        toc: &[TocEntry],
121    ) -> FloResult<Vec<Frame>> {
122        let data_start = cursor.pos;
123        let data_end = cursor.checked_end(data_size)?;
124        let mut frames = Vec::with_capacity(toc.len());
125
126        for toc_entry in toc.iter() {
127            let byte_offset = usize::try_from(toc_entry.byte_offset)
128                .map_err(|_| crate::core::FloError::from("Frame offset does not fit in memory"))?;
129            let frame_start = data_start.checked_add(byte_offset).ok_or_else(|| {
130                crate::core::FloError::from("Frame offset overflows memory address space")
131            })?;
132
133            if frame_start >= data_end {
134                return Err("Frame offset is outside DATA chunk".into());
135            }
136
137            cursor.pos = frame_start;
138            let frame_size = toc_entry.frame_size as usize;
139            let frame_end = frame_start.checked_add(frame_size).ok_or_else(|| {
140                crate::core::FloError::from("Frame size overflows memory address space")
141            })?;
142            if frame_end > data_end {
143                return Err("Frame exceeds DATA chunk".into());
144            }
145
146            let frame = self.read_frame(cursor, channels, frame_size)?;
147            frames.push(frame);
148        }
149
150        cursor.pos = data_end;
151        Ok(frames)
152    }
153
154    fn read_frame(&self, cursor: &mut Cursor, channels: u8, frame_size: usize) -> FloResult<Frame> {
155        let frame_start = cursor.pos;
156        let frame_end = frame_start.checked_add(frame_size).ok_or_else(|| {
157            crate::core::FloError::from("Frame size overflows memory address space")
158        })?;
159        if frame_end > cursor.data.len() {
160            return Err("Frame exceeds input data".into());
161        }
162
163        // frame header: type(1) + samples(4) + flags(1)
164        let frame_type_byte = cursor.read_u8()?;
165        let frame_samples = cursor.read_u32_le()?;
166        let flags = cursor.read_u8()?;
167
168        let frame_type = FrameType::from(frame_type_byte);
169        let mut frame = Frame::new(frame_type_byte, frame_samples);
170        frame.flags = flags;
171
172        // transform frames are one blob, others are per-channel
173        let num_channels_to_read = if frame_type == FrameType::Transform {
174            1
175        } else {
176            channels as usize
177        };
178
179        // read each channels data
180        for _ch_idx in 0..num_channels_to_read {
181            // channel size
182            let ch_size = cursor.read_u32_le()? as usize;
183            let ch_end = cursor.pos.checked_add(ch_size).ok_or_else(|| {
184                crate::core::FloError::from("Channel size overflows memory address space")
185            })?;
186            if ch_end > frame_end {
187                return Err("Channel exceeds frame".into());
188            }
189
190            let ch_data =
191                self.read_channel_data(cursor, frame_type, frame_samples as usize, ch_end)?;
192            frame.channels.push(ch_data);
193
194            // move to end of channel
195            cursor.pos = ch_end;
196        }
197
198        cursor.pos = frame_end;
199        Ok(frame)
200    }
201
202    fn read_channel_data(
203        &self,
204        cursor: &mut Cursor,
205        frame_type: FrameType,
206        frame_samples: usize,
207        channel_end: usize,
208    ) -> FloResult<ChannelData> {
209        if frame_samples > 2_000_000 {
210            return Err("Invalid frame: too many samples".into());
211        }
212
213        match frame_type {
214            FrameType::Silence => Ok(ChannelData::new_silence()),
215
216            FrameType::Raw => {
217                let bytes_needed = frame_samples.saturating_mul(2);
218                let available = channel_end.saturating_sub(cursor.pos);
219                let bytes_to_read = bytes_needed.min(available);
220                let residuals = cursor.read_bytes(bytes_to_read)?;
221                Ok(ChannelData::new_raw(residuals))
222            }
223
224            FrameType::Transform => {
225                // serialized mdct data
226                let remaining = channel_end.saturating_sub(cursor.pos);
227                let residuals = if remaining > 0 {
228                    cursor.read_bytes(remaining)?
229                } else {
230                    vec![]
231                };
232
233                Ok(ChannelData {
234                    predictor_coeffs: vec![],
235                    shift_bits: 0,
236                    residual_encoding: ResidualEncoding::Raw,
237                    rice_parameter: 0,
238                    residuals,
239                })
240            }
241
242            _ if frame_type.is_alpc() => {
243                // predictor order
244                let order = cursor.read_u8()? as usize;
245
246                if order > 12 {
247                    return Err("Invalid LPC order".into());
248                }
249
250                // predictor coeffs
251                let mut predictor_coeffs = Vec::with_capacity(order);
252                for _ in 0..order {
253                    if cursor
254                        .pos
255                        .checked_add(4)
256                        .is_none_or(|end| end > channel_end)
257                    {
258                        break;
259                    }
260                    predictor_coeffs.push(cursor.read_i32_le()?);
261                }
262
263                let shift_bits = cursor.read_u8()?;
264
265                let residual_encoding_byte = cursor.read_u8()?;
266                let residual_encoding = ResidualEncoding::from(residual_encoding_byte);
267
268                // rice param only for rice encoding
269                let rice_parameter = if residual_encoding == ResidualEncoding::Rice {
270                    cursor.read_u8()?
271                } else {
272                    0
273                };
274
275                // rest is residuals
276                let remaining = channel_end.saturating_sub(cursor.pos);
277                let residuals = if remaining > 0 {
278                    cursor.read_bytes(remaining)?
279                } else {
280                    vec![]
281                };
282
283                Ok(ChannelData {
284                    predictor_coeffs,
285                    shift_bits,
286                    residual_encoding,
287                    rice_parameter,
288                    residuals,
289                })
290            }
291
292            _ => Ok(ChannelData::new_silence()),
293        }
294    }
295}
296
297impl Default for Reader {
298    fn default() -> Self {
299        Self::new()
300    }
301}
302
303// cursor helper
304
305struct Cursor<'a> {
306    data: &'a [u8],
307    pos: usize,
308}
309
310impl<'a> Cursor<'a> {
311    fn new(data: &'a [u8]) -> Self {
312        Cursor { data, pos: 0 }
313    }
314
315    fn read_bytes(&mut self, count: usize) -> FloResult<Vec<u8>> {
316        let end = self.checked_end(count)?;
317        if end > self.data.len() {
318            return Err("Unexpected end of file".into());
319        }
320        let bytes = self.data[self.pos..end].to_vec();
321        self.pos = end;
322        Ok(bytes)
323    }
324
325    fn skip(&mut self, count: usize) -> FloResult<()> {
326        let end = self.checked_end(count)?;
327        if end > self.data.len() {
328            return Err("Unexpected end of file".into());
329        }
330        self.pos = end;
331        Ok(())
332    }
333
334    fn checked_end(&self, count: usize) -> FloResult<usize> {
335        self.pos
336            .checked_add(count)
337            .ok_or_else(|| "Input range overflows memory address space".into())
338    }
339
340    fn read_u8(&mut self) -> FloResult<u8> {
341        if self.pos >= self.data.len() {
342            return Err("Unexpected end of file".into());
343        }
344        let val = self.data[self.pos];
345        self.pos += 1;
346        Ok(val)
347    }
348
349    fn read_u16_le(&mut self) -> FloResult<u16> {
350        let bytes = self.read_bytes(2)?;
351        Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
352    }
353
354    fn read_u32_le(&mut self) -> FloResult<u32> {
355        let bytes = self.read_bytes(4)?;
356        Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
357    }
358
359    fn read_i32_le(&mut self) -> FloResult<i32> {
360        let bytes = self.read_bytes(4)?;
361        Ok(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
362    }
363
364    fn read_u64_le(&mut self) -> FloResult<u64> {
365        let bytes = self.read_bytes(8)?;
366        Ok(u64::from_le_bytes([
367            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
368        ]))
369    }
370}