1use rff_codec::{Codec, CodecRegistry, Decoder, Encoder};
11use rff_core::{
12 AudioFrame, Dictionary, Error, Frame, MediaType, Packet, Result, SampleFormat,
13};
14
15pub fn register(registry: &mut CodecRegistry) {
17 registry.register(Codec {
18 id: rff_core::CodecId::Flac,
19 name: "flac",
20 long_name: "FLAC (Free Lossless Audio Codec)",
21 media_type: MediaType::Audio,
22 decoder: Some(|| Box::new(FlacDecoder::default())),
23 encoder: Some(|| Box::new(FlacEncoder::new())),
24 });
25}
26
27#[derive(Default)]
32struct FlacDecoder {
33 frame: Option<Frame>,
34 eof: bool,
35}
36
37impl Decoder for FlacDecoder {
38 fn send_packet(&mut self, packet: &Packet) -> Result<()> {
39 let (info, chans) = rusty_flac::decode(&packet.data)
40 .map_err(|e| Error::invalid(format!("flac decode: {e}")))?;
41 let channels = info.channels.max(1) as usize;
42 let total = chans.first().map_or(0, |c| c.len());
43
44 let frame = if info.bits_per_sample <= 16 {
47 let shift = 16 - info.bits_per_sample; let mut bytes: Vec<u8> = vec![0u8; total * channels * 2];
49 match channels {
50 1 => {
51 for (out, &v) in bytes.chunks_exact_mut(2).zip(&chans[0]) {
52 out.copy_from_slice(&((v << shift) as i16).to_le_bytes());
53 }
54 }
55 2 => {
56 let (l, r) = (&chans[0], &chans[1]);
57 for (i, out) in bytes.chunks_exact_mut(4).enumerate() {
58 let packed = ((l[i] << shift) as i16 as u16 as u32)
60 | (((r[i] << shift) as i16 as u16 as u32) << 16);
61 out.copy_from_slice(&packed.to_le_bytes());
62 }
63 }
64 _ => {
65 for (i, out) in bytes.chunks_exact_mut(channels * 2).enumerate() {
66 for (c, chan) in chans.iter().enumerate() {
67 out[c * 2..c * 2 + 2]
68 .copy_from_slice(&((chan[i] << shift) as i16).to_le_bytes());
69 }
70 }
71 }
72 }
73 AudioFrame {
74 sample_rate: info.sample_rate,
75 channels: channels as u16,
76 format: SampleFormat::S16,
77 planes: vec![bytes],
78 samples: total,
79 pts: packet.pts,
80 }
81 } else {
82 let scale = (1u64 << (info.bits_per_sample - 1)) as f32;
84 let inv = 1.0 / scale;
85 let mut bytes: Vec<u8> = Vec::with_capacity(total * channels * 4);
86 for i in 0..total {
87 for chan in &chans {
88 bytes.extend_from_slice(&(chan[i] as f32 * inv).to_le_bytes());
89 }
90 }
91 AudioFrame {
92 sample_rate: info.sample_rate,
93 channels: channels as u16,
94 format: SampleFormat::F32,
95 planes: vec![bytes],
96 samples: total,
97 pts: packet.pts,
98 }
99 };
100 self.frame = Some(Frame::Audio(frame));
101 Ok(())
102 }
103
104 fn receive_frame(&mut self) -> Result<Frame> {
105 if let Some(frame) = self.frame.take() {
106 return Ok(frame);
107 }
108 if self.eof {
109 Err(Error::Eof)
110 } else {
111 Err(Error::Again)
112 }
113 }
114
115 fn flush(&mut self) {
116 self.eof = true;
117 }
118}
119
120struct FlacEncoder {
125 enc: Option<rusty_flac::Encoder>,
126 level: Option<u32>,
128 channels: usize,
129 scratch: Vec<i32>,
131 out: Option<Vec<u8>>,
132 flushed: bool,
133}
134
135impl FlacEncoder {
136 fn new() -> Self {
137 FlacEncoder {
138 enc: None,
139 level: None,
140 channels: 0,
141 scratch: Vec::new(),
142 out: None,
143 flushed: false,
144 }
145 }
146}
147
148#[inline]
150fn quantize(s: f32, scale: f32) -> i32 {
151 (s * scale).round().clamp(-scale, scale - 1.0) as i32
152}
153
154impl Encoder for FlacEncoder {
155 fn configure(&mut self, options: &Dictionary) -> Result<()> {
156 if let Some(level) = options.get_int("compression_level") {
157 self.level = Some(level.clamp(0, 8) as u32);
158 }
159 Ok(())
160 }
161
162 fn send_frame(&mut self, frame: &Frame) -> Result<()> {
163 let Frame::Audio(a) = frame else {
164 return Err(Error::invalid("flac encode: expected an audio frame"));
165 };
166 if self.enc.is_none() {
167 let bps = match a.format {
170 SampleFormat::S16 => 16,
171 _ => 24,
172 };
173 let channels = a.channels.max(1) as u32;
174 let mut enc = rusty_flac::Encoder::new(a.sample_rate, channels, bps)
175 .map_err(|e| Error::invalid(format!("flac encode: {e}")))?;
176 if let Some(level) = self.level {
177 enc.set_compression_level(level);
178 }
179 self.enc = Some(enc);
180 self.channels = channels as usize;
181 } else if a.channels.max(1) as usize != self.channels {
182 return Err(Error::invalid(
183 "flac encode: channel count changed mid-stream",
184 ));
185 }
186
187 let ch = self.channels;
188 let n = a.samples;
189 let enc = self.enc.as_mut().expect("encoder initialized above");
190 let map_err = |e: rusty_flac::EncodeError| Error::invalid(format!("flac encode: {e}"));
191 match a.format {
192 SampleFormat::S16 => enc
194 .push_s16le_bytes(&a.planes[0][..n * ch * 2])
195 .map_err(map_err),
196 SampleFormat::F32 => enc
197 .push_f32le_bytes(&a.planes[0][..n * ch * 4])
198 .map_err(map_err),
199 SampleFormat::F32Planar => {
200 let scale = (1i64 << 23) as f32;
201 let scratch = &mut self.scratch;
202 scratch.clear();
203 scratch.reserve(n * ch);
204 for i in 0..n {
205 for c in 0..ch {
206 let d = &a.planes[c];
207 let o = i * 4;
208 let s = f32::from_le_bytes([d[o], d[o + 1], d[o + 2], d[o + 3]]);
209 scratch.push(quantize(s, scale));
210 }
211 }
212 enc.push_interleaved(scratch).map_err(map_err)
213 }
214 _ => Err(Error::invalid(
215 "flac encode: unsupported sample format (need S16/F32/F32Planar)",
216 )),
217 }
218 }
219
220 fn receive_packet(&mut self) -> Result<Packet> {
221 if let Some(data) = self.out.take() {
222 let mut p = Packet::from_data(0, data);
223 p.pts = Some(0);
224 return Ok(p);
225 }
226 if self.flushed {
227 Err(Error::Eof)
228 } else {
229 Err(Error::Again)
230 }
231 }
232
233 fn flush(&mut self) {
234 if self.flushed {
235 return;
236 }
237 self.flushed = true;
238 if let Some(enc) = self.enc.take() {
239 self.out = Some(enc.finish());
240 }
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn decode_rejects_non_flac() {
250 let mut dec = FlacDecoder::default();
251 assert!(dec
252 .send_packet(&Packet::from_data(0, b"not flac".to_vec()))
253 .is_err());
254 }
255
256 #[test]
258 fn adapter_roundtrip_s16() {
259 let n = 6000usize;
260 let mut interleaved = Vec::with_capacity(n * 2 * 2);
261 for i in 0..n {
262 let l = ((i as f64 * 0.07).sin() * 15000.0) as i16;
263 let r = (i as i16).wrapping_mul(31);
264 interleaved.extend_from_slice(&l.to_le_bytes());
265 interleaved.extend_from_slice(&r.to_le_bytes());
266 }
267 let frame = Frame::Audio(AudioFrame {
268 sample_rate: 44100,
269 channels: 2,
270 format: SampleFormat::S16,
271 planes: vec![interleaved.clone()],
272 samples: n,
273 pts: Some(0),
274 });
275
276 let mut enc = FlacEncoder::new();
277 enc.send_frame(&frame).unwrap();
278 enc.flush();
279 let packet = enc.receive_packet().unwrap();
280
281 let (info, chans) = rusty_flac::decode(&packet.data).unwrap();
282 assert_eq!(info.bits_per_sample, 16);
283 assert_eq!(info.channels, 2);
284 for i in 0..n {
285 let l = i16::from_le_bytes([interleaved[i * 4], interleaved[i * 4 + 1]]) as i32;
286 let r = i16::from_le_bytes([interleaved[i * 4 + 2], interleaved[i * 4 + 3]]) as i32;
287 assert_eq!(chans[0][i], l);
288 assert_eq!(chans[1][i], r);
289 }
290 }
291}