noodles_cram/codecs/aac/
range_coder.rs1use 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}