add LinePack decoder
[nihav.git] / nihav-llaudio / src / codecs / flacenc.rs
CommitLineData
c11ad64e
KS
1use nihav_core::codecs::*;
2use nihav_core::io::bitwriter::*;
3use nihav_core::io::intcode::*;
4use nihav_codec_support::dsp::lpc::*;
5
6fn to_unsigned(val: i32) -> u32 {
7 if val >= 0 {
8 val as u32 * 2
9 } else {
10 -val as u32 * 2 - 1
11 }
12}
13
14fn calc_header_crc(hdr: &mut [u8]) {
15 let mut crc = 0u8;
16 let len = hdr.len() - 1;
17 for &byte in hdr[..len].iter() {
18 crc = CRC8_TABLE[(crc ^ byte) as usize];
19 }
20 hdr[len] = crc;
21}
22
23fn calc_frame_crc(buf: &mut Vec<u8>) {
24 let mut crc = 0;
25 for &byte in buf.iter() {
26 crc = (crc << 8) ^ CRC16_TABLE[(((crc >> 8) as u8) ^ byte) as usize];
27 }
28 buf.push((crc >> 8) as u8);
29 buf.push(crc as u8);
30}
31
32#[derive(Clone,Copy,Debug,PartialEq)]
33#[allow(dead_code)]
34enum StereoMode {
35 Normal,
36 LeftSide,
37 SideRight,
38 MidSide,
39}
40
41fn find_stereo_mode(samp1: &[i32], samp2: &[i32]) -> StereoMode {
42 let mut sums = [0; 3];
43 for (&l, &r) in samp1.iter().zip(samp2.iter()) {
44 sums[0] += l.abs() + r.abs();
45 sums[1] += l.abs() + (l - r).abs();
46 let b = l - r;
47 let a = r + (b >> 1);
48 sums[2] += a.abs() + b.abs();
49 }
50 let mut best_idx = 0;
51 let mut best_val = sums[0];
52 for (i, &val) in sums.iter().enumerate() {
53 if val <= best_val {
54 best_val = val;
55 best_idx = i;
56 }
57 }
58 match best_idx {
59 0 => StereoMode::Normal,
60 1 => StereoMode::LeftSide,
61 _ => StereoMode::MidSide,
62 }
63}
64
65fn apply_stereo(samp1: &mut [i32], samp2: &mut [i32], smode: StereoMode) {
66 match smode {
67 StereoMode::Normal => {},
68 StereoMode::LeftSide => {
69 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
70 *r = *l - *r;
71 }
72 },
73 StereoMode::SideRight => {
74 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
75 *l -= *r;
76 }
77 },
78 StereoMode::MidSide => {
79 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
80 let b = *l - *r;
81 *l = *r + (b >> 1);
82 *r = b;
83 }
84 },
85 };
86}
87
88fn apply_fixed_filter(dst: &mut [u32], src: &[i32], order: i8) {
89 match order {
90 -1 => {
91 let mut last = src[0];
92 for (dst, &cur) in dst[1..].iter_mut().zip(src[1..].iter()) {
93 *dst = to_unsigned(cur - last);
94 last = cur;
95 }
96 },
97 -2 => {
98 let mut last0 = src[1];
99 let mut last1 = src[0];
100 for (dst, &cur) in dst[2..].iter_mut().zip(src[2..].iter()) {
101 *dst = to_unsigned(cur - 2 * last0 + last1);
102 last1 = last0;
103 last0 = cur;
104 }
105 },
106 -3 => {
107 let mut last0 = src[2];
108 let mut last1 = src[1];
109 let mut last2 = src[0];
110 for (dst, &cur) in dst[3..].iter_mut().zip(src[3..].iter()) {
111 *dst = to_unsigned(cur - 3 * last0 + 3 * last1 - last2);
112 last2 = last1;
113 last1 = last0;
114 last0 = cur;
115 }
116 },
117 -4 => {
118 let mut last0 = src[3];
119 let mut last1 = src[2];
120 let mut last2 = src[1];
121 let mut last3 = src[0];
122 for (dst, &cur) in dst[4..].iter_mut().zip(src[4..].iter()) {
123 *dst = to_unsigned(cur - 4 * last0 + 6 * last1 - 4 * last2 + last3);
124 last3 = last2;
125 last2 = last1;
126 last1 = last0;
127 last0 = cur;
128 }
129 },
130 _ => unreachable!(),
131 };
132}
133
134fn apply_lpc(dst: &mut [u32], src: &[i32], filter: &[i32], shift: u8) {
135 let order = filter.len();
136
137 for (i, dst) in dst[order..src.len()].iter_mut().enumerate() {
138 let sum = src[i..].iter().zip(filter.iter()).fold(0, |acc, (&c, &f)| acc + i64::from(c) * i64::from(f));
139 *dst = to_unsigned(src[i + order] - ((sum >> shift) as i32));
140 }
141}
142
143fn encode_residual(bw: &mut BitWriter, src: &[u32]) {
051abe1f 144 let sum = src.iter().sum::<u32>() / (src.len() as u32);
c11ad64e
KS
145
146 let k = (31 - sum.max(1).leading_zeros()) as u8;
147 if k < 16 {
148 bw.write(0, 2);
149 bw.write(0, 4); // 1 partition
150 bw.write(u32::from(k), 4);
151 } else {
152 bw.write(1, 2);
153 bw.write(0, 4); // 1 partition
154 bw.write(u32::from(k), 5);
155 }
156 for &samp in src.iter() {
157 bw.write_code(UintCodeType::Rice(k), samp);
158 }
159}
160
161#[derive(Default)]
162struct FLACEncoder {
163 stream: Option<NAStreamRef>,
164 channels: usize,
165 srate: u32,
166 block_len: usize,
167 order: i8,
168 samples: Vec<Vec<i32>>,
169 flush: bool,
170 cur_pos: usize,
171 tmp: Vec<u32>,
172 ffilter: [f64; 32],
173 ifilter: [i32; 32],
174}
175
051abe1f 176#[allow(clippy::match_overlapping_arm)]
c11ad64e
KS
177fn nsamples_code(nsamp: usize) -> u8 {
178 match nsamp {
179 192 => 1,
180 576 => 2,
181 1152 => 3,
182 2304 => 4,
183 4608 => 5,
184 256 => 8,
185 512 => 9,
186 1024 => 10,
187 2048 => 11,
188 4096 => 12,
189 8192 => 13,
190 16384 => 14,
191 32768 => 15,
192 0..=255 => 6,
193 _ => 7,
194 }
195}
196
197fn encode_nsamples_esc(bw: &mut BitWriter, nsamp: usize, code: u8) {
198 match code {
199 6 => {
200 bw.write((nsamp - 1) as u32, 8);
201 },
202 7 => {
203 bw.write((nsamp - 1) as u32, 16);
204 },
205 _ => {},
206 };
207}
208
209fn write_utf8(bw: &mut BitWriter, val: usize) {
210 let val = val as u32;
211 let lz = 32 - val.leading_zeros();
212 match lz {
213 0..=7 => {
214 bw.write(val, 8);
215 },
216 8..=11 => {
217 bw.write(0xC0 | (val >> 6), 8);
218 bw.write(0x80 | (val & 0x3F), 8);
219 },
220 12..=16 => {
221 bw.write(0xE0 | ( val >> 12), 8);
222 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
223 bw.write(0x80 | ( val & 0x3F), 8);
224 },
225 17..=21 => {
226 bw.write(0xF0 | ( val >> 18), 8);
227 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
228 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
229 bw.write(0x80 | ( val & 0x3F), 8);
230 },
231 22..=26 => {
232 bw.write(0xF8 | ( val >> 24), 8);
233 bw.write(0x80 | ((val >> 18) & 0x3F), 8);
234 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
235 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
236 bw.write(0x80 | ( val & 0x3F), 8);
237 },
238 _ => {
239 bw.write(0xFC | ( val >> 30), 8);
240 bw.write(0x80 | ((val >> 24) & 0x3F), 8);
241 bw.write(0x80 | ((val >> 18) & 0x3F), 8);
242 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
243 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
244 bw.write(0x80 | ( val & 0x3F), 8);
245 },
246 };
247}
248
249const DEFAULT_BLOCK_LEN: usize = 4096;
250
251impl FLACEncoder {
252 fn new() -> Self { Self::default() }
253 fn encode_packet(&mut self) -> EncoderResult<NAPacket> {
254 if self.samples[0].is_empty() || (!self.flush && self.samples[0].len() < self.block_len) {
255 return Err(EncoderError::TryAgain);
256 }
257
258 let nsamples = self.samples[0].len().min(self.block_len);
259
260 let mut bw = BitWriter::new(Vec::with_capacity(1024), BitWriterMode::BE);
261 bw.write(0x3FFE, 14);
262 bw.write0(); // reserved
263 bw.write1(); // blocking strategy - variable
264 let scode = nsamples_code(nsamples);
265 bw.write(u32::from(scode), 4);
266 bw.write(0x0, 4); // sample rate - read the stream info
267 let smode = if self.channels == 2 {
268 let (l, r) = self.samples.split_at_mut(1);
269 let smode = find_stereo_mode(&l[0][..nsamples], &r[0][..nsamples]);
270 apply_stereo(&mut l[0][..nsamples], &mut r[0][..nsamples], smode);
271 smode
272 } else {
273 StereoMode::Normal
274 };
275 let chan_idx = match smode {
276 StereoMode::Normal => (self.channels as u32) - 1,
277 StereoMode::LeftSide => 8,
278 StereoMode::SideRight => 9,
279 StereoMode::MidSide => 10,
280 };
281 bw.write(chan_idx, 4);
282 bw.write(0x4, 3); // 16 bits per sample
283 bw.write0(); // reserved
284 write_utf8(&mut bw, self.cur_pos);
285 encode_nsamples_esc(&mut bw, nsamples, scode);
286 // optional bits per sample
287 bw.write(0x00, 8); // header CRC placeholder
288 let hdr_crc_pos = bw.tell() >> 3;
289 for chan in 0..self.channels {
290 let samp_bits = match (smode, chan) {
291 (StereoMode::LeftSide, 1) |
292 (StereoMode::SideRight, 0) |
293 (StereoMode::MidSide, 1) => 16 + 1,
294 _ => 16,
295 };
296 self.encode_channel(&mut bw, chan, nsamples, samp_bits);
297 }
298
299 let mut dbuf = bw.end();
300 calc_header_crc(&mut dbuf[..hdr_crc_pos]);
301 calc_frame_crc(&mut dbuf);
3fae33bd 302 let ts = NATimeInfo::new(Some(self.cur_pos as u64), None, Some(nsamples as u64), 1, self.srate);
c11ad64e
KS
303
304 for samp in self.samples.iter_mut() {
305 samp.drain(..nsamples);
306 }
307 self.cur_pos += nsamples;
308
309 Ok(NAPacket::new(self.stream.clone().unwrap(), ts, true, dbuf))
310 }
311 fn encode_channel(&mut self, bw: &mut BitWriter, chan: usize, nsamples: usize, samp_bits: u8) {
312 let samp = &self.samples[chan][..nsamples];
313
314 let s0 = samp[0];
315 let mut same = true;
316 for &s in samp[1..].iter() {
317 if s != s0 {
318 same = false;
319 break;
320 }
321 }
322
323 bw.write0();
324 if !same {
325 match self.order {
326 0 => {
327 bw.write(1, 6);
328 bw.write0(); // no wasted bits
329 for &el in samp.iter() {
051abe1f 330 bw.write_s(el, samp_bits);
c11ad64e
KS
331 }
332 },
333 -1 | -2 | -3 | -4 => {
334 let order = -self.order as usize;
335
336 apply_fixed_filter(&mut self.tmp, samp, self.order);
337
338 bw.write(8 | (order as u32), 6);
339 bw.write0(); // no wasted bits
340 for &el in samp[..order].iter() {
051abe1f 341 bw.write_s(el, samp_bits);
c11ad64e
KS
342 }
343 encode_residual(bw, &self.tmp[order..nsamples]);
344 },
345 _ => {
346 let order = self.order as usize;
347 calc_lpc_filter(samp, &mut self.ffilter[..order]);
348
349 let mut filter_prec = 12;
350 let scale = f64::from(1 << filter_prec);
351
352 let maxval = (self.ffilter[..order].iter().fold(0.0, |acc: f64, &el| acc.max(el.abs())) * scale) as i32;
353 let mut mask = 0;
354 for (dst, &src) in self.ifilter[..order].iter_mut().zip(&self.ffilter) {
355 *dst = (src * scale) as i32;
356 mask |= *dst;
357 }
358 let mut zbits = mask.trailing_zeros();
359 let mut filter_bits = 33 - maxval.leading_zeros() - zbits;
360 if filter_bits > 15 {
361 let sub = filter_bits - 15;
362 zbits += sub;
363 filter_bits = 15;
364 }
365 filter_prec -= zbits;
366 if zbits > 0 {
367 for el in self.ifilter[..order].iter_mut() {
368 *el >>= zbits;
369 }
370 }
371
372 apply_lpc(&mut self.tmp, samp, &self.ifilter[..order], filter_prec as u8);
373
374 bw.write(0x20 | ((order - 1) as u32), 6);
375 bw.write0(); // no wasted bits
376 for &el in samp[..order].iter() {
051abe1f 377 bw.write_s(el, samp_bits);
c11ad64e
KS
378 }
379 bw.write(filter_bits - 1, 4);
380 bw.write(filter_prec, 5);
381 for &coef in self.ifilter[..order].iter().rev() {
382 bw.write_s(coef, filter_bits as u8);
383 }
384 encode_residual(bw, &self.tmp[order..nsamples]);
385 },
386 };
387 } else {
388 bw.write(0, 6);
389 bw.write0(); // no wasted bits
390 bw.write(u32::from(s0 as u16), samp_bits);
391 }
392 }
393}
394
395impl NAEncoder for FLACEncoder {
396 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
397 match encinfo.format {
398 NACodecTypeInfo::None => {
6f263099
KS
399 Ok(EncodeParameters {
400 format: NACodecTypeInfo::Audio(NAAudioInfo::new(0, 1, SND_S16_FORMAT, DEFAULT_BLOCK_LEN)),
401 ..Default::default() })
c11ad64e
KS
402 },
403 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
404 NACodecTypeInfo::Audio(ainfo) => {
405 let mut outinfo = ainfo;
406 outinfo.channels = outinfo.channels.max(1).min(8);
407 if outinfo.format != SND_S16P_FORMAT && outinfo.format != SND_S16_FORMAT {
408 outinfo.format = SND_S16P_FORMAT;
409 }
410 if outinfo.block_len == 0 {
411 outinfo.block_len = DEFAULT_BLOCK_LEN;
412 }
413 outinfo.block_len = outinfo.block_len.max(2).min(65535);
414 let mut ofmt = *encinfo;
415 ofmt.format = NACodecTypeInfo::Audio(outinfo);
416 Ok(ofmt)
417 }
418 }
419 }
2757a028 420 fn get_capabilities(&self) -> u64 { 0 }
c11ad64e
KS
421 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
422 match encinfo.format {
423 NACodecTypeInfo::None => Err(EncoderError::FormatError),
424 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
425 NACodecTypeInfo::Audio(ainfo) => {
426 if ainfo.format != SND_S16P_FORMAT && ainfo.format != SND_S16_FORMAT {
427 return Err(EncoderError::FormatError);
428 }
429 if ainfo.block_len == 0 {
430 self.block_len = DEFAULT_BLOCK_LEN;
431 } else {
432 if ainfo.block_len < 2 || ainfo.block_len > 65535 {
433 return Err(EncoderError::FormatError);
434 }
435 self.block_len = ainfo.block_len;
436 }
437 if ainfo.channels == 0 || ainfo.channels > 8 {
438 return Err(EncoderError::FormatError);
439 }
440 self.channels = ainfo.channels as usize;
441
442 let soniton = SND_S16P_FORMAT;
443 let out_ainfo = NAAudioInfo::new(ainfo.sample_rate, ainfo.channels, soniton, self.block_len);
444 let info = NACodecInfo::new("flac", NACodecTypeInfo::Audio(out_ainfo), None);
445 let mut stream = NAStream::new(StreamType::Audio, stream_id, info, 1, ainfo.sample_rate, 0);
446 stream.set_num(stream_id as usize);
447 let stream = stream.into_ref();
448
449 self.stream = Some(stream.clone());
450 self.srate = ainfo.sample_rate;
451
452 self.samples.clear();
453 for _ in 0..self.channels {
454 self.samples.push(Vec::with_capacity(DEFAULT_BLOCK_LEN));
455 }
456 self.tmp.resize(self.block_len, 0);
457
458 Ok(stream)
459 },
460 }
461 }
462 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
463 let buf = frm.get_buffer();
464 if let Some(ref abuf) = buf.get_abuf_i16() {
465 let src = abuf.get_data();
466 let len = abuf.get_length();
467 if abuf.get_step() == 1 {
468 let astride = abuf.get_stride();
469 let mut off = 0;
470 for dst in self.samples.iter_mut() {
471 dst.reserve(len);
472 for &samp in src[off..][..len].iter() {
473 dst.push(i32::from(samp));
474 }
475 off += astride;
476 }
477 } else {
478 for dst in self.samples.iter_mut() {
479 dst.reserve(len);
480 }
481 let mut src = src.iter();
482 for _ in 0..len {
483 for dst in self.samples.iter_mut() {
484 dst.push(i32::from(*src.next().unwrap()));
485 }
486 }
487 }
488 Ok(())
489 } else {
490 Err(EncoderError::InvalidParameters)
491 }
492 }
493 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
494 if let Ok(pkt) = self.encode_packet() {
495 Ok(Some(pkt))
496 } else {
497 Ok(None)
498 }
499 }
500 fn flush(&mut self) -> EncoderResult<()> {
501 self.flush = true;
502 Ok(())
503 }
504}
505
506const ENCODER_OPTS: &[NAOptionDefinition] = &[
507 NAOptionDefinition {
508 name: "order", description: "LPC order",
509 opt_type: NAOptionDefinitionType::Int(Some(-4), Some(32)) },
510 NAOptionDefinition {
511 name: "block_size", description: "block size",
512 opt_type: NAOptionDefinitionType::Int(Some(2), Some(65535)) },
513];
514
515impl NAOptionHandler for FLACEncoder {
516 fn get_supported_options(&self) -> &[NAOptionDefinition] { ENCODER_OPTS }
517 fn set_options(&mut self, options: &[NAOption]) {
518 for option in options.iter() {
519 for opt_def in ENCODER_OPTS.iter() {
520 if opt_def.check(option).is_ok() {
521 match option.name {
522 "order" => {
523 if let NAValue::Int(val) = option.value {
524 self.order = val as i8;
525 }
526 },
527 "block_size" => {
528 if let NAValue::Int(val) = option.value {
529 self.block_len = val as usize;
530 self.tmp.resize(self.block_len, 0);
531 }
532 },
533 _ => {},
534 };
535 }
536 }
537 }
538 }
539 fn query_option_value(&self, name: &str) -> Option<NAValue> {
540 match name {
541 "order" => Some(NAValue::Int(i64::from(self.order))),
542 "block_size" => Some(NAValue::Int(self.block_len as i64)),
543 _ => None,
544 }
545 }
546}
547
548pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
549 Box::new(FLACEncoder::new())
550}
551
552#[cfg(test)]
553mod test {
554 use nihav_core::codecs::*;
555 use nihav_core::demuxers::*;
556 use nihav_core::muxers::*;
557 use nihav_codec_support::test::enc_video::*;
558 use crate::*;
559
560 #[test]
561 fn test_flac_encoder_verbatim() {
562 let enc_options = &[
563 NAOption{name: "order", value: NAValue::Int(0)},
564 ];
565 test_flac_encoder("uncompr.flac", enc_options,
566 &[0xcd9767ee, 0xf8a86d20, 0x317944aa, 0xd9044f5c]);
567 }
568 #[test]
569 fn test_flac_encoder_fixed1() {
570 let enc_options = &[
571 NAOption{name: "order", value: NAValue::Int(-1)},
572 ];
573 test_flac_encoder("fixed1.flac", enc_options,
574 &[0xcf654f93, 0x1db0bb07, 0xbc0cd9c3, 0xf9d2cc4e]);
575 }
576 #[test]
577 fn test_flac_encoder_fixed4() {
578 let enc_options = &[
579 NAOption{name: "order", value: NAValue::Int(-4)},
580 ];
581 test_flac_encoder("fixed1.flac", enc_options,
582 &[0xbc2fba7f, 0x6f9406ee, 0x98be1f67, 0xe2b86b2d]);
583 }
584 #[test]
585 fn test_flac_encoder_lpc10() {
586 let enc_options = &[
587 NAOption{name: "order", value: NAValue::Int(10)},
588 ];
589 test_flac_encoder("lpc10.flac", enc_options,
590 &[0xb6736f2e, 0xb61dda7a, 0xeb4037db, 0x8ee4afb9]);
591 }
592
593 fn test_flac_encoder(name: &'static str, enc_options: &[NAOption], hash: &[u32; 4]) {
594 let mut dmx_reg = RegisteredDemuxers::new();
595 llaudio_register_all_demuxers(&mut dmx_reg);
596 let mut dec_reg = RegisteredDecoders::new();
597 llaudio_register_all_decoders(&mut dec_reg);
598 let mut mux_reg = RegisteredMuxers::new();
599 llaudio_register_all_muxers(&mut mux_reg);
600 let mut enc_reg = RegisteredEncoders::new();
601 llaudio_register_all_encoders(&mut enc_reg);
602
886cde48 603 // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
c11ad64e
KS
604 let dec_config = DecoderTestParams {
605 demuxer: "flac",
606 in_name: "assets/LLaudio/luckynight.flac",
607 stream_type: StreamType::Audio,
608 limit: Some(10),
609 dmx_reg, dec_reg,
610 };
611 let enc_config = EncoderTestParams {
612 muxer: "flac",
613 enc_name: "flac",
614 out_name: name,
615 mux_reg, enc_reg,
616 };
617 let dst_ainfo = NAAudioInfo {
618 sample_rate: 0,
619 channels: 0,
620 format: SND_S16_FORMAT,
621 block_len: 0,
622 };
623 let enc_params = EncodeParameters {
624 format: NACodecTypeInfo::Audio(dst_ainfo),
625 quality: 0,
626 bitrate: 0,
627 tb_num: 0,
628 tb_den: 0,
629 flags: 0,
630 };
631// test_encoding_to_file(&dec_config, &enc_config, enc_params, enc_options);
632
633 test_encoding_md5(&dec_config, &enc_config, enc_params, enc_options,
634 hash);
635 }
636}
637
638const CRC8_TABLE: [u8; 256] = [
639 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
640 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
641 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
642 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
643 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
644 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
645 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
646 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
647 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
648 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
649 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
650 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
651 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
652 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
653 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
654 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
655 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
656 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
657 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
658 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
659 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
660 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
661 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
662 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
663 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
664 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
665 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
666 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
667 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
668 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
669 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
670 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
671];
672
673const CRC16_TABLE: [u16; 256] = [
674 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
675 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
676 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
677 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
678 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
679 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
680 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
681 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
682 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
683 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
684 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
685 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
686 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
687 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
688 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
689 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
690 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
691 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
692 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
693 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
694 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
695 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
696 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
697 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
698 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
699 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
700 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
701 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
702 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
703 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
704 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
705 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
706];