Skip to main content

pito_codecs/ac3/
mod.rs

1#![allow(clippy::needless_range_loop)]
2
3mod aht;
4mod aht_tables;
5mod bits;
6mod block;
7mod eac3;
8mod header;
9mod imdct;
10mod tables;
11
12pub use header::frame_len;
13
14use bits::Bits;
15use block::{CHANNELS, LFE, State};
16use header::{Header, Kind};
17use imdct::Imdct;
18
19use crate::media::{AudioBuffer, Error, Packet, Result};
20
21const K: f32 = std::f32::consts::FRAC_1_SQRT_2;
22const MAX_SAMPLES: usize = 1536;
23
24const SL: usize = 6;
25const SR: usize = 7;
26const BL: usize = 4;
27const BR: usize = 5;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub struct Info {
31    pub rate: u32,
32    pub channels: u16,
33    pub eac3: bool,
34}
35
36pub fn info(frame: &[u8]) -> Result<Info> {
37    let h = header::parse(frame)?;
38    Ok(Info {
39        rate: h.rate,
40        channels: h.nchans() as u16,
41        eac3: h.eac3,
42    })
43}
44
45pub fn layout(channels: u16) -> u16 {
46    match channels {
47        0 | 1 => 1,
48        2 => 2,
49        3..=6 => 6,
50        _ => 8,
51    }
52}
53
54fn locations(acmod: u8, lfeon: bool) -> ([u8; 6], usize) {
55    let (front, n): ([u8; 5], usize) = match acmod {
56        0 | 2 => ([0, 2, 0, 0, 0], 2),
57        1 => ([1, 0, 0, 0, 0], 1),
58        3 => ([0, 1, 2, 0, 0], 3),
59        4 => ([0, 2, 16, 0, 0], 3),
60        5 => ([0, 1, 2, 16, 0], 4),
61        6 => ([0, 2, 3, 4, 0], 4),
62        _ => ([0, 1, 2, 3, 4], 5),
63    };
64    let mut out = [0u8; 6];
65    out[..5].copy_from_slice(&front);
66    if lfeon {
67        out[n] = 15;
68    }
69    (out, n + lfeon as usize)
70}
71
72fn chanmap_locations(map: u16, n: usize) -> Option<[u8; 16]> {
73    let mut out = [0u8; 16];
74    let mut k = 0;
75    for bit in 0..16u8 {
76        if map & (0x8000 >> bit) == 0 {
77            continue;
78        }
79        let pair = matches!(bit, 5 | 6 | 9 | 10 | 11 | 13);
80        for side in 0..1 + pair as u8 {
81            if k >= 16 {
82                return None;
83            }
84            out[k] = bit | (side << 5);
85            k += 1;
86        }
87    }
88    (k == n).then_some(out)
89}
90
91fn slots(loc: u8) -> &'static [(usize, f32)] {
92    let right = loc & 0x20 != 0;
93    match (loc & 0x1F, right) {
94        (0, _) => &[(0, 1.0)],
95        (1, _) => &[(2, 1.0)],
96        (2, _) => &[(1, 1.0)],
97        (3, _) => &[(SL, 1.0)],
98        (4, _) => &[(SR, 1.0)],
99        (5, false) => &[(0, K), (2, K)],
100        (5, true) => &[(1, K), (2, K)],
101        (6, false) => &[(BL, 1.0)],
102        (6, true) => &[(BR, 1.0)],
103        (7, _) => &[(BL, K), (BR, K)],
104        (8, _) => &[(SL, 0.5), (SR, 0.5)],
105        (9, false) => &[(SL, 1.0)],
106        (9, true) => &[(SR, 1.0)],
107        (10, false) => &[(0, 1.0)],
108        (10, true) => &[(1, 1.0)],
109        (11, false) => &[(0, K)],
110        (11, true) => &[(1, K)],
111        (12, _) => &[(2, K)],
112        (13, false) => &[(SL, K)],
113        (13, true) => &[(SR, K)],
114        (16, _) => &[(SL, K), (SR, K)],
115        _ => &[(3, 1.0)],
116    }
117}
118
119struct Sub {
120    state: State,
121    pcm: Box<[[f32; MAX_SAMPLES]; CHANNELS]>,
122    order: [usize; 6],
123    locs: [u8; 16],
124    n: usize,
125    samples: usize,
126    live: bool,
127}
128
129impl Sub {
130    fn new() -> Sub {
131        Sub {
132            state: State::new(),
133            pcm: Box::new([[0.0; MAX_SAMPLES]; CHANNELS]),
134            order: [0; 6],
135            locs: [0; 16],
136            n: 0,
137            samples: 0,
138            live: false,
139        }
140    }
141}
142
143pub struct Decoder {
144    rate: u32,
145    channels: u16,
146    imdct: Imdct,
147    subs: Vec<Sub>,
148    time: Box<[[[f32; 512]; CHANNELS]; 6]>,
149    slots: Box<[[f32; MAX_SAMPLES]; 8]>,
150    nodither: bool,
151}
152
153impl Decoder {
154    pub fn new(rate: u32, channels: u16) -> Decoder {
155        Decoder {
156            rate,
157            channels: layout(channels),
158            imdct: Imdct::new(),
159            subs: Vec::new(),
160            time: Box::new([[[0.0; 512]; CHANNELS]; 6]),
161            slots: Box::new([[0.0; MAX_SAMPLES]; 8]),
162            nodither: false,
163        }
164    }
165
166    pub fn rate(&self) -> u32 {
167        self.rate
168    }
169
170    pub fn channels(&self) -> u16 {
171        self.channels
172    }
173
174    pub fn reset(&mut self) {
175        self.subs.clear();
176    }
177
178    #[cfg(test)]
179    pub(crate) fn without_dither(mut self) -> Decoder {
180        self.nodither = true;
181        self
182    }
183
184    #[cfg(test)]
185    pub(crate) fn holes(&mut self) -> Vec<usize> {
186        self.subs
187            .first_mut()
188            .map(|s| std::mem::take(&mut s.state.holes))
189            .unwrap_or_default()
190    }
191
192    #[cfg(test)]
193    pub(crate) fn marks(&mut self) -> Vec<usize> {
194        self.subs
195            .first_mut()
196            .map(|s| std::mem::take(&mut s.state.marks))
197            .unwrap_or_default()
198    }
199
200    pub fn decode(&mut self, packet: &Packet) -> Result<AudioBuffer> {
201        self.decode_frame(&packet.data)
202    }
203
204    pub fn decode_frame(&mut self, data: &[u8]) -> Result<AudioBuffer> {
205        let mut out = AudioBuffer::new(self.rate, self.channels);
206        self.decode_into(data, &mut out.samples)?;
207        Ok(out)
208    }
209
210    pub fn decode_into(&mut self, data: &[u8], out: &mut Vec<f32>) -> Result<()> {
211        out.clear();
212        let mut pos = 0;
213        let mut open = false;
214        while data.len() - pos >= 6 {
215            let rest = &data[pos..];
216            let h = header::parse(rest)?;
217            let frame = rest.get(..h.bytes).ok_or_else(|| {
218                Error::Invalid(format!(
219                    "AC-3 frame of {} bytes in {} remaining",
220                    h.bytes,
221                    rest.len()
222                ))
223            })?;
224            pos += h.bytes;
225            let slot = match (h.kind, h.substream) {
226                (Kind::Independent | Kind::Convert, 0) => 0,
227                (Kind::Dependent, k) if open => 1 + k as usize,
228                _ => continue,
229            };
230            if slot == 0 {
231                if open {
232                    self.render(out);
233                }
234                for s in self.subs.iter_mut() {
235                    s.live = false;
236                }
237                self.rate = h.rate;
238                open = true;
239            }
240            while self.subs.len() <= slot {
241                self.subs.push(Sub::new());
242            }
243            if let Err(e) = self.substream(slot, &h, frame) {
244                self.subs[slot] = Sub::new();
245                return Err(e);
246            }
247        }
248        if !open {
249            return Err(Error::Invalid(
250                "AC-3 packet without an independent frame".into(),
251            ));
252        }
253        self.render(out);
254        Ok(())
255    }
256
257    fn substream(&mut self, slot: usize, h: &Header, frame: &[u8]) -> Result<()> {
258        let samples = h.blocks * 256;
259        if slot > 0 && self.subs[0].samples != samples {
260            return Err(Error::Invalid(
261                "E-AC-3 dependent frame with a different block count".into(),
262            ));
263        }
264        let sub = &mut self.subs[slot];
265        sub.state.nodither = self.nodither;
266        let mut b = Bits::new(frame);
267        b.skip(h.bits)?;
268        if h.eac3 {
269            eac3::decode(&mut sub.state, &mut b, h)?;
270        } else {
271            for blk in 0..6 {
272                sub.state.blk = blk;
273                block::read_block_ac3(&mut sub.state, &mut b, h, blk)?;
274                block::dsp(&mut sub.state, h.nfchans, h.acmod);
275                sub.state.mark(h.nfchans, h.lfeon);
276            }
277        }
278        let chans: Vec<usize> = (0..h.nfchans).chain(h.lfeon.then_some(LFE)).collect();
279        let mut spec = Vec::with_capacity(36);
280        let mut short = Vec::with_capacity(36);
281        let mut time = Vec::with_capacity(36);
282        for (blk, t) in self.time.iter_mut().enumerate().take(h.blocks) {
283            for (ch, t) in t.iter_mut().enumerate() {
284                if chans.contains(&ch) {
285                    spec.push(&sub.state.spec[blk][ch]);
286                    short.push(sub.state.short[blk][ch]);
287                    time.push(t);
288                }
289            }
290        }
291        self.imdct.run(&spec, &short, &mut time);
292        for &ch in &chans {
293            for blk in 0..h.blocks {
294                let c = &mut sub.state.ch[ch];
295                self.imdct.overlap(
296                    &self.time[blk][ch],
297                    &mut c.delay,
298                    sub.state.gain[blk][ch],
299                    &mut sub.pcm[ch][blk * 256..blk * 256 + 256],
300                );
301            }
302        }
303        let (locs, n) = locations(h.acmod, h.lfeon);
304        sub.order = std::array::from_fn(|i| chans.get(i).copied().unwrap_or(0));
305        sub.n = n;
306        sub.locs = [0; 16];
307        match h.chanmap.filter(|_| slot > 0) {
308            Some(map) => {
309                sub.locs = chanmap_locations(map, n).ok_or_else(|| {
310                    Error::Invalid("E-AC-3 channel map does not match its channels".into())
311                })?;
312            }
313            None => sub.locs[..6].copy_from_slice(&locs),
314        }
315        sub.samples = samples;
316        sub.live = true;
317        Ok(())
318    }
319
320    fn render(&mut self, out: &mut Vec<f32>) {
321        let Some(main) = self.subs.first() else {
322            return;
323        };
324        let samples = main.samples;
325        let mut sources: Vec<(u8, usize, usize)> = (0..main.n)
326            .map(|i| (main.locs[i], 0, main.order[i]))
327            .collect();
328        for (k, sub) in self.subs.iter().enumerate().skip(1) {
329            if !sub.live || sub.samples != samples {
330                continue;
331            }
332            for i in 0..sub.n.min(6) {
333                let src = (sub.locs[i], k, sub.order[i]);
334                match sources.iter_mut().find(|s| s.0 == src.0) {
335                    Some(s) => *s = src,
336                    None => sources.push(src),
337                }
338            }
339        }
340        let only_center = sources.iter().all(|s| s.0 == 1 || s.0 == 15);
341        for s in self.slots.iter_mut() {
342            s[..samples].fill(0.0);
343        }
344        for &(loc, k, ch) in &sources {
345            let pcm = &self.subs[k].pcm[ch];
346            for &(slot, g) in slots(loc) {
347                for (o, &v) in self.slots[slot][..samples].iter_mut().zip(&pcm[..samples]) {
348                    *o += v * g;
349                }
350            }
351        }
352        let s = &self.slots;
353        let n = self.channels as usize;
354        let base = out.len();
355        out.resize(base + samples * n, 0.0);
356        let dst = &mut out[base..];
357        match n {
358            8 => {
359                for (i, f) in dst.chunks_exact_mut(8).enumerate() {
360                    for (c, v) in f.iter_mut().enumerate() {
361                        *v = s[c][i];
362                    }
363                }
364            }
365            6 => {
366                for (i, f) in dst.chunks_exact_mut(6).enumerate() {
367                    f[0] = s[0][i];
368                    f[1] = s[1][i];
369                    f[2] = s[2][i];
370                    f[3] = s[3][i];
371                    f[4] = s[SL][i] + K * s[BL][i];
372                    f[5] = s[SR][i] + K * s[BR][i];
373                }
374            }
375            _ if only_center => {
376                for (i, f) in dst.chunks_exact_mut(n).enumerate() {
377                    f.fill(s[2][i]);
378                }
379            }
380            2 => {
381                for (i, f) in dst.chunks_exact_mut(2).enumerate() {
382                    let c = K * s[2][i];
383                    f[0] = s[0][i] + c + K * (s[SL][i] + s[BL][i]);
384                    f[1] = s[1][i] + c + K * (s[SR][i] + s[BR][i]);
385                }
386            }
387            _ => {
388                for (i, v) in dst.iter_mut().enumerate() {
389                    let c = K * s[2][i];
390                    let l = s[0][i] + c + K * (s[SL][i] + s[BL][i]);
391                    let r = s[1][i] + c + K * (s[SR][i] + s[BR][i]);
392                    *v = 0.5 * (l + r);
393                }
394            }
395        }
396    }
397}
398
399#[cfg(test)]
400mod tests;