noodles_cram/codecs/aac/
range_coder.rs

1use std::io::{self, Read, Write};
2
3use crate::io::{reader::num::read_u8, writer::num::write_u8};
4
5#[derive(Debug)]
6pub struct RangeCoder {
7    range: u32,
8    code: u32,
9
10    low: u32,
11    carry: u32,
12    cache: u32,
13    ff_num: u32,
14}
15
16impl RangeCoder {
17    pub fn range_decode_create<R>(&mut self, reader: &mut R) -> io::Result<()>
18    where
19        R: Read,
20    {
21        for _ in 0..=4 {
22            let b = read_u8(reader).map(u32::from)?;
23            self.code = (self.code << 8) | b;
24        }
25
26        self.code &= u32::MAX;
27
28        Ok(())
29    }
30
31    pub fn range_get_freq(&mut self, tot_freq: u32) -> u32 {
32        self.range /= tot_freq;
33        self.code / self.range
34    }
35
36    pub fn range_decode<R>(&mut self, reader: &mut R, sym_low: u32, sym_freq: u32) -> io::Result<()>
37    where
38        R: Read,
39    {
40        self.code -= sym_low * self.range;
41        self.range *= sym_freq;
42
43        while self.range < (1 << 24) {
44            self.range <<= 8;
45            let b = read_u8(reader).map(u32::from)?;
46            self.code = (self.code << 8) | b;
47        }
48
49        Ok(())
50    }
51
52    pub fn range_encode<W>(
53        &mut self,
54        writer: &mut W,
55        sym_low: u32,
56        sym_freq: u32,
57        tot_freq: u32,
58    ) -> io::Result<()>
59    where
60        W: Write,
61    {
62        let old_low = self.low;
63
64        self.range /= tot_freq;
65        self.low = self.low.overflowing_add(sym_low * self.range).0;
66        self.range *= sym_freq;
67
68        if self.low < old_low {
69            self.carry = 1;
70        }
71
72        while self.range < (1 << 24) {
73            self.range <<= 8;
74            self.range_shift_low(writer)?;
75        }
76
77        Ok(())
78    }
79
80    fn range_shift_low<W>(&mut self, writer: &mut W) -> io::Result<()>
81    where
82        W: Write,
83    {
84        if self.low < 0xff000000 || self.carry != 0 {
85            if self.carry == 0 {
86                let b = (self.cache & 0xff) as u8;
87                write_u8(writer, b)?;
88
89                while self.ff_num > 0 {
90                    write_u8(writer, 0xff)?;
91                    self.ff_num -= 1;
92                }
93            } else {
94                let b = ((self.cache + 1) & 0xff) as u8;
95                write_u8(writer, b)?;
96
97                while self.ff_num > 0 {
98                    write_u8(writer, 0x00)?;
99                    self.ff_num -= 1;
100                }
101            }
102
103            self.cache = self.low >> 24;
104            self.carry = 0;
105        } else {
106            self.ff_num += 1;
107        }
108
109        self.low <<= 8;
110
111        Ok(())
112    }
113
114    pub fn range_encode_end<W>(&mut self, writer: &mut W) -> io::Result<()>
115    where
116        W: Write,
117    {
118        for _ in 0..=4 {
119            self.range_shift_low(writer)?;
120        }
121
122        Ok(())
123    }
124}
125
126impl Default for RangeCoder {
127    fn default() -> Self {
128        Self {
129            range: u32::MAX,
130            code: 0,
131
132            low: 0,
133            carry: 0,
134            cache: 0,
135            ff_num: 0,
136        }
137    }
138}