]>
Commit | Line | Data |
---|---|---|
87927c57 KS |
1 | use nihav_core::codecs::*; |
2 | use nihav_core::io::byteio::*; | |
3 | use nihav_core::io::bitreader::*; | |
4 | use nihav_core::io::intcode::*; | |
5 | ||
6 | #[derive(Default)] | |
7 | struct Filter { | |
8 | predictor: i32, | |
9 | error: i32, | |
10 | round: i32, | |
11 | shift: u8, | |
12 | qm: [i32; 8], | |
13 | dx: [i32; 8], | |
14 | dl: [i32; 8], | |
15 | } | |
16 | ||
17 | impl Filter { | |
18 | fn reset(&mut self, bpp: u8) { | |
19 | const SHIFTS: [u8; 3] = [10, 9, 10]; | |
20 | self.shift = SHIFTS[(bpp - 1) as usize]; | |
21 | self.round = (1 << self.shift) >> 1; | |
22 | self.error = 0; | |
23 | self.qm = [0; 8]; | |
24 | self.dx = [0; 8]; | |
25 | self.dl = [0; 8]; | |
26 | self.predictor = 0; | |
27 | } | |
28 | fn hybrid_filt(&mut self, delta: i32) -> i32 { | |
29 | if self.error < 0 { | |
30 | for (qm, dx) in self.qm.iter_mut().zip(self.dx.iter()) { | |
31 | *qm -= *dx; | |
32 | } | |
33 | } else if self.error > 0 { | |
34 | for (qm, dx) in self.qm.iter_mut().zip(self.dx.iter()) { | |
35 | *qm += *dx; | |
36 | } | |
37 | } | |
38 | ||
39 | let mut sum = self.round; | |
40 | for (dl, qm) in self.dl.iter().zip(self.qm.iter()) { | |
41 | sum = sum.wrapping_add(*dl * *qm); | |
42 | } | |
43 | self.error = delta; | |
44 | let val = (sum >> self.shift) + delta; | |
45 | ||
46 | for i in 0..4 { | |
47 | self.dx[i] = self.dx[i + 1]; | |
48 | self.dl[i] = self.dl[i + 1]; | |
49 | } | |
50 | self.dx[4] = (self.dl[4] >> 30) | 1; | |
51 | self.dx[5] = ((self.dl[5] >> 30) | 2) & !1; | |
52 | self.dx[6] = ((self.dl[6] >> 30) | 2) & !1; | |
53 | self.dx[7] = ((self.dl[7] >> 30) | 4) & !3; | |
54 | self.dl[4] = -self.dl[5]; | |
55 | self.dl[5] = -self.dl[6]; | |
56 | self.dl[6] = val - self.dl[7]; | |
57 | self.dl[7] = val; | |
58 | self.dl[5] += self.dl[6]; | |
59 | self.dl[4] += self.dl[5]; | |
60 | ||
61 | val | |
62 | } | |
63 | fn static_pred(&mut self, bpp: u8, mut val: i32) -> i32 { | |
64 | val += match bpp { | |
65 | 0 => ((i64::from(self.predictor) * 15) >> 4) as i32, | |
66 | 1 | 2 => ((i64::from(self.predictor) * 31) >> 5) as i32, | |
67 | _ => self.predictor, | |
68 | }; | |
69 | self.predictor = val; | |
70 | val | |
71 | } | |
72 | } | |
73 | ||
74 | struct RiceDecoder { | |
75 | k: u8, | |
76 | sum: u32, | |
77 | } | |
78 | ||
79 | impl RiceDecoder { | |
80 | fn new() -> Self { | |
81 | let k = 10; | |
82 | Self { | |
83 | k, sum: RiceDecoder::limit(k) | |
84 | } | |
85 | } | |
86 | fn reset(&mut self) { | |
87 | self.k = 10; | |
88 | self.sum = RiceDecoder::limit(self.k); | |
89 | } | |
90 | fn limit(k: u8) -> u32 { 1 << (k + 4).min(31) } | |
91 | fn update(&mut self, val: u32) { | |
92 | self.sum -= self.sum >> 4; | |
93 | self.sum += val; | |
94 | if self.k > 0 && self.sum < Self::limit(self.k) { | |
95 | self.k -= 1; | |
96 | } else if self.sum > Self::limit(self.k + 1) { | |
97 | self.k += 1; | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | trait Output { | |
103 | fn set(&mut self, val: i32); | |
104 | } | |
105 | ||
106 | impl Output for i16 { | |
107 | fn set(&mut self, val: i32) { *self = val as i16; } | |
108 | } | |
109 | impl Output for i32 { | |
110 | fn set(&mut self, val: i32) { *self = val; } | |
111 | } | |
112 | ||
113 | struct ChannelDecoder { | |
114 | filt: Filter, | |
115 | rice0: RiceDecoder, | |
116 | rice1: RiceDecoder, | |
117 | offset: usize, | |
118 | sample: i32, | |
119 | } | |
120 | ||
121 | impl ChannelDecoder { | |
122 | fn new() -> Self { | |
123 | Self { | |
124 | filt: Filter::default(), | |
125 | rice0: RiceDecoder::new(), | |
126 | rice1: RiceDecoder::new(), | |
127 | offset: 0, | |
128 | sample: 0, | |
129 | } | |
130 | } | |
131 | } | |
132 | ||
133 | struct TTADecoder { | |
134 | ainfo: NAAudioInfo, | |
135 | chmap: NAChannelMap, | |
136 | bpp: u8, | |
137 | framelen: u32, | |
138 | nsamples: u32, | |
139 | ch_dec: Vec<ChannelDecoder>, | |
140 | } | |
141 | ||
142 | impl TTADecoder { | |
143 | fn new() -> Self { | |
144 | Self { | |
145 | ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), | |
146 | chmap: NAChannelMap::new(), | |
147 | bpp: 0, | |
148 | framelen: 0, | |
149 | nsamples: 0, | |
150 | ch_dec: Vec::new(), | |
151 | } | |
152 | } | |
153 | fn decode_frame<T: Output>(&mut self, br: &mut BitReader, dst: &mut [T], stride: usize) -> DecoderResult<bool> { | |
154 | for (i, chdec) in self.ch_dec.iter_mut().enumerate() { | |
155 | chdec.offset = i * stride; | |
156 | chdec.rice0.reset(); | |
157 | chdec.rice1.reset(); | |
158 | chdec.filt.reset(self.bpp); | |
159 | } | |
160 | ||
161 | let channels = self.ch_dec.len(); | |
162 | let tail_len = self.nsamples % self.framelen; | |
163 | ||
164 | for sample in 0..self.framelen { | |
165 | for chdec in self.ch_dec.iter_mut() { | |
166 | let pfx = br.read_code(UintCodeType::UnaryOnes)?; | |
167 | let (k, pfx, level1) = if pfx == 0 { | |
168 | (chdec.rice0.k, 0, false) | |
169 | } else { | |
170 | (chdec.rice1.k, pfx - 1, true) | |
171 | }; | |
172 | let mut val = (pfx << k) | br.read(k)?; | |
173 | if level1 { | |
174 | chdec.rice1.update(val); | |
175 | val += 1 << chdec.rice0.k; | |
176 | } | |
177 | chdec.rice0.update(val); | |
178 | let delta = if (val & 1) == 0 { | |
179 | -((val >> 1) as i32) | |
180 | } else { | |
181 | ((val + 1) >> 1) as i32 | |
182 | }; | |
183 | let hval = chdec.filt.hybrid_filt(delta); | |
184 | chdec.sample = chdec.filt.static_pred(self.bpp, hval); | |
185 | } | |
186 | if channels > 1 { | |
187 | self.ch_dec[channels - 1].sample += self.ch_dec[channels - 2].sample / 2; | |
188 | let mut last = self.ch_dec[channels - 1].sample; | |
189 | for chdec in self.ch_dec.iter_mut().rev().skip(1) { | |
190 | chdec.sample = last - chdec.sample; | |
191 | last = chdec.sample; | |
192 | } | |
193 | } | |
194 | for chdec in self.ch_dec.iter_mut() { | |
195 | dst[chdec.offset].set(chdec.sample); | |
196 | chdec.offset += 1; | |
197 | } | |
198 | if (tail_len > 0) && (sample == tail_len - 1) && (br.left() < 40) { | |
199 | return Ok(false); | |
200 | } | |
201 | } | |
202 | ||
203 | Ok(true) | |
204 | } | |
205 | } | |
206 | ||
207 | fn check_crc(buf: &[u8]) -> bool { | |
208 | if buf.len() <= 4 { | |
209 | return false; | |
210 | } | |
211 | let mut crc = 0xFFFFFFFF; | |
212 | let ref_crc = read_u32le(&buf[buf.len() - 4..]).unwrap_or(0); | |
213 | for el in buf.iter().take(buf.len() - 4) { | |
214 | crc = CRC32_TAB[(crc as u8 ^ *el) as usize] ^ (crc >> 8); | |
215 | } | |
216 | crc == !ref_crc | |
217 | } | |
218 | ||
219 | impl NADecoder for TTADecoder { | |
220 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { | |
221 | if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { | |
222 | if let Some(buf) = info.get_extradata() { | |
223 | if !check_crc(&buf) { | |
224 | return Err(DecoderError::ChecksumError); | |
225 | } | |
226 | let mut mr = MemoryReader::new_read(&buf); | |
227 | let mut br = ByteReader::new(&mut mr); | |
228 | let tag = br.read_tag()?; | |
229 | validate!(&tag == b"TTA1"); | |
230 | let afmt = br.read_u16le()?; | |
231 | if afmt != 1 { | |
232 | return Err(DecoderError::NotImplemented); | |
233 | } | |
234 | let channels = br.read_u16le()?; | |
235 | validate!(channels > 0 && channels < 256); | |
236 | let bpp = br.read_u16le()?; | |
237 | validate!(bpp > 0 && bpp <= 32); | |
238 | let srate = br.read_u32le()?; | |
239 | validate!(srate > 256 && srate < 1048576); | |
240 | self.nsamples = br.read_u32le()?; | |
241 | validate!(self.nsamples > 0); | |
242 | ||
243 | self.framelen = srate * 256 / 245; | |
244 | ||
245 | self.chmap = if channels == 1 { | |
246 | NAChannelMap::from_str("C").unwrap() | |
247 | } else if channels == 2 { | |
248 | NAChannelMap::from_str("L,R").unwrap() | |
249 | } else { | |
250 | return Err(DecoderError::NotImplemented); | |
251 | }; | |
252 | let fmt = match bpp { | |
253 | 8 | 16 => SND_S16P_FORMAT, | |
254 | 24 | 32 => SND_S32P_FORMAT, | |
255 | _ => return Err(DecoderError::NotImplemented), | |
256 | }; | |
257 | self.bpp = (bpp / 8) as u8; | |
258 | self.ch_dec = Vec::with_capacity(channels as usize); | |
259 | for _ in 0..channels { | |
260 | self.ch_dec.push(ChannelDecoder::new()); | |
261 | } | |
262 | ||
263 | self.ainfo = NAAudioInfo::new(srate, channels as u8, fmt, self.framelen as usize); | |
264 | Ok(()) | |
265 | } else { | |
266 | Err(DecoderError::InvalidData) | |
267 | } | |
268 | } else { | |
269 | Err(DecoderError::InvalidData) | |
270 | } | |
271 | } | |
272 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
273 | let info = pkt.get_stream().get_info(); | |
274 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { | |
275 | let pktbuf = pkt.get_buffer(); | |
276 | validate!(pktbuf.len() > 4); | |
277 | if !check_crc(&pktbuf) { | |
278 | return Err(DecoderError::ChecksumError); | |
279 | } | |
280 | ||
281 | let mut br = BitReader::new(&pktbuf, BitReaderMode::LE); | |
282 | ||
283 | let mut abuf = alloc_audio_buffer(self.ainfo, self.framelen as usize, self.chmap.clone())?; | |
284 | let duration = match abuf { | |
285 | NABufferType::AudioI16(ref mut adata) => { | |
286 | let stride = adata.get_stride(); | |
287 | let dst = adata.get_data_mut().unwrap(); | |
288 | let not_last = self.decode_frame(&mut br, dst, stride)?; | |
289 | if not_last { | |
290 | self.framelen | |
291 | } else { | |
87927c57 KS |
292 | self.nsamples % self.framelen |
293 | } | |
294 | }, | |
295 | NABufferType::AudioI32(ref mut adata) => { | |
296 | let stride = adata.get_stride(); | |
297 | let dst = adata.get_data_mut().unwrap(); | |
298 | let not_last = self.decode_frame(&mut br, dst, stride)?; | |
299 | if not_last { | |
300 | self.framelen | |
301 | } else { | |
87927c57 KS |
302 | self.nsamples % self.framelen |
303 | } | |
304 | }, | |
305 | _ => unreachable!(), | |
306 | }; | |
2d1e0773 | 307 | abuf.truncate_audio(duration as usize); |
87927c57 KS |
308 | |
309 | let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); | |
310 | frm.set_duration(Some(u64::from(duration))); | |
311 | Ok(frm.into_ref()) | |
312 | } else { | |
313 | Err(DecoderError::InvalidData) | |
314 | } | |
315 | } | |
316 | fn flush(&mut self) { | |
317 | } | |
318 | } | |
319 | ||
320 | impl NAOptionHandler for TTADecoder { | |
321 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
322 | fn set_options(&mut self, _options: &[NAOption]) { } | |
323 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
324 | } | |
325 | ||
326 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { | |
327 | Box::new(TTADecoder::new()) | |
328 | } | |
329 | ||
330 | #[cfg(test)] | |
331 | mod test { | |
332 | use nihav_core::codecs::RegisteredDecoders; | |
333 | use nihav_core::demuxers::RegisteredDemuxers; | |
334 | use nihav_codec_support::test::dec_video::*; | |
335 | use crate::llaudio_register_all_decoders; | |
336 | use crate::llaudio_register_all_demuxers; | |
337 | #[test] | |
338 | fn test_tta() { | |
339 | let mut dmx_reg = RegisteredDemuxers::new(); | |
340 | llaudio_register_all_demuxers(&mut dmx_reg); | |
341 | let mut dec_reg = RegisteredDecoders::new(); | |
342 | llaudio_register_all_decoders(&mut dec_reg); | |
343 | ||
344 | test_decoding("tta", "tta", "assets/LLaudio/luckynight.tta", Some(3), &dmx_reg, &dec_reg, | |
345 | ExpectedTestResult::MD5([0xce0fe9c4, 0xa69eefda, 0xe182008c, 0xe941db3f])); | |
346 | } | |
347 | } | |
348 | ||
349 | const CRC32_TAB: [u32; 256] = [ | |
350 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, | |
351 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | |
352 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | |
353 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | |
354 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, | |
355 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | |
356 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, | |
357 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | |
358 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | |
359 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | |
360 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, | |
361 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | |
362 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, | |
363 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | |
364 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | |
365 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | |
366 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, | |
367 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | |
368 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, | |
369 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | |
370 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | |
371 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | |
372 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, | |
373 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | |
374 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, | |
375 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | |
376 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | |
377 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | |
378 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, | |
379 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | |
380 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, | |
381 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | |
382 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | |
383 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | |
384 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, | |
385 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | |
386 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, | |
387 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | |
388 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | |
389 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | |
390 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, | |
391 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | |
392 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, | |
393 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | |
394 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | |
395 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | |
396 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, | |
397 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | |
398 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, | |
399 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | |
400 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | |
401 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | |
402 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, | |
403 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | |
404 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, | |
405 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | |
406 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | |
407 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | |
408 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, | |
409 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | |
410 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, | |
411 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | |
412 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | |
413 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d | |
414 | ]; |