1#[derive(Debug, Clone)]
16pub struct AecParams {
17 pub bits_per_sample: u32,
19 pub block_size: u32,
21 pub rsi: u32,
23 pub flags: u32,
25}
26
27pub const AEC_DATA_SIGNED: u32 = 1;
31pub const AEC_DATA_3BYTE: u32 = 2;
33pub const AEC_DATA_MSB: u32 = 4;
35pub const AEC_DATA_PREPROCESS: u32 = 8;
37pub const AEC_ALLOW_K13: u32 = 16;
39pub const AEC_PAD_RSI: u32 = 32;
41pub const AEC_NOT_ENFORCE: u32 = 64;
43pub const AEC_RESTRICTED: u32 = 128;
45
46pub(crate) fn sample_byte_width(bits_per_sample: u32, flags: u32) -> usize {
50 let nbytes = (bits_per_sample as usize).div_ceil(8);
51 if nbytes == 3 && flags & AEC_DATA_3BYTE == 0 {
52 4 } else {
54 nbytes
55 }
56}
57
58pub(crate) fn effective_flags(params: &AecParams) -> u32 {
63 let mut flags = params.flags;
64 if params.bits_per_sample > 16 && params.bits_per_sample <= 24 {
65 flags |= AEC_DATA_3BYTE;
66 }
67 flags
68}
69
70pub(crate) fn id_len(bits_per_sample: u32, flags: u32) -> u32 {
81 if bits_per_sample > 16 {
82 5
83 } else if bits_per_sample > 8 {
84 4
85 } else if flags & AEC_RESTRICTED != 0 {
86 if bits_per_sample <= 2 {
87 1
88 } else {
89 2 }
91 } else {
92 3
93 }
94}
95
96pub(crate) fn kmax(id_len: u32) -> u32 {
98 (1u32 << id_len).saturating_sub(3)
99}
100
101pub(crate) fn validate(params: &AecParams) -> Result<(), crate::AecError> {
103 use crate::AecError;
104
105 if params.bits_per_sample == 0 || params.bits_per_sample > 32 {
106 return Err(AecError::Config(format!(
107 "bits_per_sample must be 1–32, got {}",
108 params.bits_per_sample
109 )));
110 }
111
112 if params.block_size == 0 {
113 return Err(AecError::Config("block_size must be non-zero".to_string()));
114 }
115 if params.flags & AEC_NOT_ENFORCE != 0 {
116 if params.block_size & 1 != 0 {
117 return Err(AecError::Config(format!(
118 "block_size must be even, got {}",
119 params.block_size
120 )));
121 }
122 } else if !matches!(params.block_size, 8 | 16 | 32 | 64) {
123 return Err(AecError::Config(format!(
124 "block_size must be 8, 16, 32, or 64, got {}",
125 params.block_size
126 )));
127 }
128
129 if params.rsi == 0 || params.rsi > 4096 {
130 return Err(AecError::Config(format!(
131 "rsi must be 1–4096, got {}",
132 params.rsi
133 )));
134 }
135
136 if params.flags & AEC_RESTRICTED != 0 && params.bits_per_sample > 4 {
137 return Err(AecError::Config(format!(
138 "AEC_RESTRICTED requires bits_per_sample ≤ 4, got {}",
139 params.bits_per_sample
140 )));
141 }
142
143 Ok(())
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_id_len_values() {
152 assert_eq!(id_len(32, 0), 5);
153 assert_eq!(id_len(24, 0), 5);
154 assert_eq!(id_len(17, 0), 5);
155 assert_eq!(id_len(16, 0), 4);
156 assert_eq!(id_len(9, 0), 4);
157 assert_eq!(id_len(8, 0), 3);
158 assert_eq!(id_len(1, 0), 3);
159 assert_eq!(id_len(2, AEC_RESTRICTED), 1);
160 assert_eq!(id_len(4, AEC_RESTRICTED), 2);
161 }
162
163 #[test]
164 fn test_kmax_values() {
165 assert_eq!(kmax(5), 29);
166 assert_eq!(kmax(4), 13);
167 assert_eq!(kmax(3), 5);
168 assert_eq!(kmax(2), 1);
169 assert_eq!(kmax(1), 0); }
171
172 #[test]
173 fn test_sample_byte_width() {
174 assert_eq!(sample_byte_width(8, 0), 1);
175 assert_eq!(sample_byte_width(16, 0), 2);
176 assert_eq!(sample_byte_width(24, 0), 4); assert_eq!(sample_byte_width(24, AEC_DATA_3BYTE), 3);
178 assert_eq!(sample_byte_width(32, 0), 4);
179 }
180
181 #[test]
182 fn test_effective_flags_auto_3byte() {
183 let p = AecParams {
184 bits_per_sample: 24,
185 block_size: 16,
186 rsi: 128,
187 flags: AEC_DATA_PREPROCESS,
188 };
189 let f = effective_flags(&p);
190 assert!(f & AEC_DATA_3BYTE != 0);
191 assert!(f & AEC_DATA_PREPROCESS != 0);
192 }
193
194 #[test]
195 fn test_validate_ok() {
196 let p = AecParams {
197 bits_per_sample: 8,
198 block_size: 16,
199 rsi: 128,
200 flags: AEC_DATA_PREPROCESS,
201 };
202 assert!(validate(&p).is_ok());
203 }
204
205 #[test]
206 fn test_validate_bad_bps() {
207 let p = AecParams {
208 bits_per_sample: 0,
209 block_size: 16,
210 rsi: 128,
211 flags: 0,
212 };
213 assert!(validate(&p).is_err());
214
215 let p2 = AecParams {
216 bits_per_sample: 33,
217 block_size: 16,
218 rsi: 128,
219 flags: 0,
220 };
221 assert!(validate(&p2).is_err());
222 }
223
224 #[test]
225 fn test_validate_bad_block_size() {
226 let p = AecParams {
227 bits_per_sample: 8,
228 block_size: 12,
229 rsi: 128,
230 flags: 0,
231 };
232 assert!(validate(&p).is_err());
233
234 let p2 = AecParams {
236 bits_per_sample: 8,
237 block_size: 12,
238 rsi: 128,
239 flags: AEC_NOT_ENFORCE,
240 };
241 assert!(validate(&p2).is_ok());
242 }
243}