]> git.nihav.org Git - nihav.git/blob - nihav-llaudio/src/codecs/flacenc.rs
add bytes_left() to NAPacketiser so its internal buffer size can be monitored
[nihav.git] / nihav-llaudio / src / codecs / flacenc.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::bitwriter::*;
3 use nihav_core::io::intcode::*;
4 use nihav_codec_support::dsp::lpc::*;
5
6 fn 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
14 fn 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
23 fn 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)]
34 enum StereoMode {
35 Normal,
36 LeftSide,
37 SideRight,
38 MidSide,
39 }
40
41 fn 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
65 fn 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
88 fn 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
134 fn 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
143 fn encode_residual(bw: &mut BitWriter, src: &[u32]) {
144 let sum = src.iter().sum::<u32>() / (src.len() as u32);
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)]
162 struct 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
176 #[allow(clippy::match_overlapping_arm)]
177 fn 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
197 fn 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
209 fn 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
249 const DEFAULT_BLOCK_LEN: usize = 4096;
250
251 impl 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);
302 let ts = NATimeInfo::new(Some(self.cur_pos as u64), None, Some(nsamples as u64), 1, self.srate);
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() {
330 bw.write_s(el, samp_bits);
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() {
341 bw.write_s(el, samp_bits);
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() {
377 bw.write_s(el, samp_bits);
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
395 impl NAEncoder for FLACEncoder {
396 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
397 match encinfo.format {
398 NACodecTypeInfo::None => {
399 let mut ofmt = EncodeParameters::default();
400 ofmt.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 1, SND_S16_FORMAT, DEFAULT_BLOCK_LEN));
401 Ok(ofmt)
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 }
420 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
421 match encinfo.format {
422 NACodecTypeInfo::None => Err(EncoderError::FormatError),
423 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
424 NACodecTypeInfo::Audio(ainfo) => {
425 if ainfo.format != SND_S16P_FORMAT && ainfo.format != SND_S16_FORMAT {
426 return Err(EncoderError::FormatError);
427 }
428 if ainfo.block_len == 0 {
429 self.block_len = DEFAULT_BLOCK_LEN;
430 } else {
431 if ainfo.block_len < 2 || ainfo.block_len > 65535 {
432 return Err(EncoderError::FormatError);
433 }
434 self.block_len = ainfo.block_len;
435 }
436 if ainfo.channels == 0 || ainfo.channels > 8 {
437 return Err(EncoderError::FormatError);
438 }
439 self.channels = ainfo.channels as usize;
440
441 let soniton = SND_S16P_FORMAT;
442 let out_ainfo = NAAudioInfo::new(ainfo.sample_rate, ainfo.channels, soniton, self.block_len);
443 let info = NACodecInfo::new("flac", NACodecTypeInfo::Audio(out_ainfo), None);
444 let mut stream = NAStream::new(StreamType::Audio, stream_id, info, 1, ainfo.sample_rate, 0);
445 stream.set_num(stream_id as usize);
446 let stream = stream.into_ref();
447
448 self.stream = Some(stream.clone());
449 self.srate = ainfo.sample_rate;
450
451 self.samples.clear();
452 for _ in 0..self.channels {
453 self.samples.push(Vec::with_capacity(DEFAULT_BLOCK_LEN));
454 }
455 self.tmp.resize(self.block_len, 0);
456
457 Ok(stream)
458 },
459 }
460 }
461 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
462 let buf = frm.get_buffer();
463 if let Some(ref abuf) = buf.get_abuf_i16() {
464 let src = abuf.get_data();
465 let len = abuf.get_length();
466 if abuf.get_step() == 1 {
467 let astride = abuf.get_stride();
468 let mut off = 0;
469 for dst in self.samples.iter_mut() {
470 dst.reserve(len);
471 for &samp in src[off..][..len].iter() {
472 dst.push(i32::from(samp));
473 }
474 off += astride;
475 }
476 } else {
477 for dst in self.samples.iter_mut() {
478 dst.reserve(len);
479 }
480 let mut src = src.iter();
481 for _ in 0..len {
482 for dst in self.samples.iter_mut() {
483 dst.push(i32::from(*src.next().unwrap()));
484 }
485 }
486 }
487 Ok(())
488 } else {
489 Err(EncoderError::InvalidParameters)
490 }
491 }
492 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
493 if let Ok(pkt) = self.encode_packet() {
494 Ok(Some(pkt))
495 } else {
496 Ok(None)
497 }
498 }
499 fn flush(&mut self) -> EncoderResult<()> {
500 self.flush = true;
501 Ok(())
502 }
503 }
504
505 const ENCODER_OPTS: &[NAOptionDefinition] = &[
506 NAOptionDefinition {
507 name: "order", description: "LPC order",
508 opt_type: NAOptionDefinitionType::Int(Some(-4), Some(32)) },
509 NAOptionDefinition {
510 name: "block_size", description: "block size",
511 opt_type: NAOptionDefinitionType::Int(Some(2), Some(65535)) },
512 ];
513
514 impl NAOptionHandler for FLACEncoder {
515 fn get_supported_options(&self) -> &[NAOptionDefinition] { ENCODER_OPTS }
516 fn set_options(&mut self, options: &[NAOption]) {
517 for option in options.iter() {
518 for opt_def in ENCODER_OPTS.iter() {
519 if opt_def.check(option).is_ok() {
520 match option.name {
521 "order" => {
522 if let NAValue::Int(val) = option.value {
523 self.order = val as i8;
524 }
525 },
526 "block_size" => {
527 if let NAValue::Int(val) = option.value {
528 self.block_len = val as usize;
529 self.tmp.resize(self.block_len, 0);
530 }
531 },
532 _ => {},
533 };
534 }
535 }
536 }
537 }
538 fn query_option_value(&self, name: &str) -> Option<NAValue> {
539 match name {
540 "order" => Some(NAValue::Int(i64::from(self.order))),
541 "block_size" => Some(NAValue::Int(self.block_len as i64)),
542 _ => None,
543 }
544 }
545 }
546
547 pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
548 Box::new(FLACEncoder::new())
549 }
550
551 #[cfg(test)]
552 mod test {
553 use nihav_core::codecs::*;
554 use nihav_core::demuxers::*;
555 use nihav_core::muxers::*;
556 use nihav_codec_support::test::enc_video::*;
557 use crate::*;
558
559 #[test]
560 fn test_flac_encoder_verbatim() {
561 let enc_options = &[
562 NAOption{name: "order", value: NAValue::Int(0)},
563 ];
564 test_flac_encoder("uncompr.flac", enc_options,
565 &[0xcd9767ee, 0xf8a86d20, 0x317944aa, 0xd9044f5c]);
566 }
567 #[test]
568 fn test_flac_encoder_fixed1() {
569 let enc_options = &[
570 NAOption{name: "order", value: NAValue::Int(-1)},
571 ];
572 test_flac_encoder("fixed1.flac", enc_options,
573 &[0xcf654f93, 0x1db0bb07, 0xbc0cd9c3, 0xf9d2cc4e]);
574 }
575 #[test]
576 fn test_flac_encoder_fixed4() {
577 let enc_options = &[
578 NAOption{name: "order", value: NAValue::Int(-4)},
579 ];
580 test_flac_encoder("fixed1.flac", enc_options,
581 &[0xbc2fba7f, 0x6f9406ee, 0x98be1f67, 0xe2b86b2d]);
582 }
583 #[test]
584 fn test_flac_encoder_lpc10() {
585 let enc_options = &[
586 NAOption{name: "order", value: NAValue::Int(10)},
587 ];
588 test_flac_encoder("lpc10.flac", enc_options,
589 &[0xb6736f2e, 0xb61dda7a, 0xeb4037db, 0x8ee4afb9]);
590 }
591
592 fn test_flac_encoder(name: &'static str, enc_options: &[NAOption], hash: &[u32; 4]) {
593 let mut dmx_reg = RegisteredDemuxers::new();
594 llaudio_register_all_demuxers(&mut dmx_reg);
595 let mut dec_reg = RegisteredDecoders::new();
596 llaudio_register_all_decoders(&mut dec_reg);
597 let mut mux_reg = RegisteredMuxers::new();
598 llaudio_register_all_muxers(&mut mux_reg);
599 let mut enc_reg = RegisteredEncoders::new();
600 llaudio_register_all_encoders(&mut enc_reg);
601
602 let dec_config = DecoderTestParams {
603 demuxer: "flac",
604 in_name: "assets/LLaudio/luckynight.flac",
605 stream_type: StreamType::Audio,
606 limit: Some(10),
607 dmx_reg, dec_reg,
608 };
609 let enc_config = EncoderTestParams {
610 muxer: "flac",
611 enc_name: "flac",
612 out_name: name,
613 mux_reg, enc_reg,
614 };
615 let dst_ainfo = NAAudioInfo {
616 sample_rate: 0,
617 channels: 0,
618 format: SND_S16_FORMAT,
619 block_len: 0,
620 };
621 let enc_params = EncodeParameters {
622 format: NACodecTypeInfo::Audio(dst_ainfo),
623 quality: 0,
624 bitrate: 0,
625 tb_num: 0,
626 tb_den: 0,
627 flags: 0,
628 };
629 // test_encoding_to_file(&dec_config, &enc_config, enc_params, enc_options);
630
631 test_encoding_md5(&dec_config, &enc_config, enc_params, enc_options,
632 hash);
633 }
634 }
635
636 const CRC8_TABLE: [u8; 256] = [
637 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
638 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
639 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
640 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
641 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
642 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
643 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
644 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
645 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
646 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
647 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
648 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
649 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
650 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
651 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
652 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
653 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
654 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
655 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
656 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
657 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
658 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
659 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
660 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
661 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
662 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
663 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
664 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
665 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
666 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
667 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
668 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
669 ];
670
671 const CRC16_TABLE: [u16; 256] = [
672 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
673 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
674 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
675 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
676 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
677 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
678 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
679 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
680 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
681 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
682 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
683 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
684 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
685 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
686 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
687 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
688 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
689 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
690 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
691 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
692 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
693 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
694 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
695 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
696 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
697 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
698 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
699 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
700 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
701 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
702 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
703 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
704 ];