Skip to main content

rff_codec_flac/
lib.rs

1//! FLAC lossless audio **decoder**, backed by the pure-Rust [`claxon`]
2//! (Apache-2.0, no FFI).
3//!
4//! FLAC is self-describing (its `STREAMINFO` carries sample rate / channels /
5//! bit depth), so — like the image codecs — a packet is the whole `.flac`
6//! stream and no [`configure`](rff_codec::Decoder::configure) is needed. The
7//! whole stream decodes to one interleaved `f32` [`AudioFrame`] (samples
8//! normalized from FLAC's native bit depth).
9//!
10//! Decode is via `claxon`; **encode** is our own in-house lossless encoder
11//! ([`encode`], built brick by brick — see `docs/codec-flac-encoder.md`).
12
13use std::io::Cursor;
14
15use claxon::FlacReader;
16use rff_codec::{Codec, CodecRegistry, Decoder};
17use rff_core::{AudioFrame, Error, Frame, MediaType, Packet, Result, SampleFormat};
18
19mod encode;
20mod md5;
21
22/// Register the FLAC codec (decode only) into a [`CodecRegistry`].
23pub fn register(registry: &mut CodecRegistry) {
24    registry.register(Codec {
25        id: rff_core::CodecId::Flac,
26        name: "flac",
27        long_name: "FLAC (Free Lossless Audio Codec)",
28        media_type: MediaType::Audio,
29        decoder: Some(|| Box::new(FlacDecoder::default())),
30        encoder: Some(|| Box::new(encode::FlacEncoder::new())),
31    });
32}
33
34#[derive(Default)]
35struct FlacDecoder {
36    frame: Option<Frame>,
37    eof: bool,
38}
39
40impl Decoder for FlacDecoder {
41    fn send_packet(&mut self, packet: &Packet) -> Result<()> {
42        let mut reader = FlacReader::new(Cursor::new(&packet.data))
43            .map_err(|e| Error::invalid(format!("flac decode: {e}")))?;
44        let info = reader.streaminfo();
45        let channels = info.channels.max(1) as usize;
46        // Normalize native integer samples to f32 in [-1, 1).
47        let scale = (1u64 << info.bits_per_sample.saturating_sub(1).max(1)) as f32;
48
49        let mut floats = Vec::new();
50        for sample in reader.samples() {
51            let v = sample.map_err(|e| Error::invalid(format!("flac decode: {e}")))?;
52            floats.push(v as f32 / scale);
53        }
54        let total = floats.len();
55        let bytes: Vec<u8> = floats.iter().flat_map(|s| s.to_le_bytes()).collect();
56
57        self.frame = Some(Frame::Audio(AudioFrame {
58            sample_rate: info.sample_rate,
59            channels: channels as u16,
60            format: SampleFormat::F32,
61            planes: vec![bytes],
62            samples: total / channels,
63            pts: packet.pts,
64        }));
65        Ok(())
66    }
67
68    fn receive_frame(&mut self) -> Result<Frame> {
69        if let Some(frame) = self.frame.take() {
70            return Ok(frame);
71        }
72        if self.eof {
73            Err(Error::Eof)
74        } else {
75            Err(Error::Again)
76        }
77    }
78
79    fn flush(&mut self) {
80        self.eof = true;
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn decode_rejects_non_flac() {
90        let mut dec = FlacDecoder::default();
91        assert!(dec
92            .send_packet(&Packet::from_data(0, b"not flac".to_vec()))
93            .is_err());
94    }
95}