1 use nihav_core::codecs::*;
2 use nihav_core::io::bitwriter::*;
3 use nihav_core::io::intcode::*;
4 use nihav_codec_support::dsp::lpc::*;
6 fn to_unsigned(val: i32) -> u32 {
14 fn calc_header_crc(hdr: &mut [u8]) {
16 let len = hdr.len() - 1;
17 for &byte in hdr[..len].iter() {
18 crc = CRC8_TABLE[(crc ^ byte) as usize];
23 fn calc_frame_crc(buf: &mut Vec<u8>) {
25 for &byte in buf.iter() {
26 crc = (crc << 8) ^ CRC16_TABLE[(((crc >> 8) as u8) ^ byte) as usize];
28 buf.push((crc >> 8) as u8);
32 #[derive(Clone,Copy,Debug,PartialEq)]
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();
48 sums[2] += a.abs() + b.abs();
51 let mut best_val = sums[0];
52 for (i, &val) in sums.iter().enumerate() {
59 0 => StereoMode::Normal,
60 1 => StereoMode::LeftSide,
61 _ => StereoMode::MidSide,
65 fn apply_stereo(samp1: &mut [i32], samp2: &mut [i32], smode: StereoMode) {
67 StereoMode::Normal => {},
68 StereoMode::LeftSide => {
69 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
73 StereoMode::SideRight => {
74 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
78 StereoMode::MidSide => {
79 for (l, r) in samp1.iter_mut().zip(samp2.iter_mut()) {
88 fn apply_fixed_filter(dst: &mut [u32], src: &[i32], order: i8) {
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);
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);
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);
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);
134 fn apply_lpc(dst: &mut [u32], src: &[i32], filter: &[i32], shift: u8) {
135 let order = filter.len();
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));
143 fn encode_residual(bw: &mut BitWriter, src: &[u32]) {
144 let sum = src.iter().sum::<u32>() / (src.len() as u32);
146 let k = (31 - sum.max(1).leading_zeros()) as u8;
149 bw.write(0, 4); // 1 partition
150 bw.write(u32::from(k), 4);
153 bw.write(0, 4); // 1 partition
154 bw.write(u32::from(k), 5);
156 for &samp in src.iter() {
157 bw.write_code(UintCodeType::Rice(k), samp);
163 stream: Option<NAStreamRef>,
168 samples: Vec<Vec<i32>>,
176 #[allow(clippy::match_overlapping_arm)]
177 fn nsamples_code(nsamp: usize) -> u8 {
197 fn encode_nsamples_esc(bw: &mut BitWriter, nsamp: usize, code: u8) {
200 bw.write((nsamp - 1) as u32, 8);
203 bw.write((nsamp - 1) as u32, 16);
209 fn write_utf8(bw: &mut BitWriter, val: usize) {
210 let val = val as u32;
211 let lz = 32 - val.leading_zeros();
217 bw.write(0xC0 | (val >> 6), 8);
218 bw.write(0x80 | (val & 0x3F), 8);
221 bw.write(0xE0 | ( val >> 12), 8);
222 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
223 bw.write(0x80 | ( val & 0x3F), 8);
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);
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);
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);
249 const DEFAULT_BLOCK_LEN: usize = 4096;
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);
258 let nsamples = self.samples[0].len().min(self.block_len);
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);
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,
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,
296 self.encode_channel(&mut bw, chan, nsamples, samp_bits);
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);
304 for samp in self.samples.iter_mut() {
305 samp.drain(..nsamples);
307 self.cur_pos += nsamples;
309 Ok(NAPacket::new(self.stream.clone().unwrap(), ts, true, dbuf))
311 fn encode_channel(&mut self, bw: &mut BitWriter, chan: usize, nsamples: usize, samp_bits: u8) {
312 let samp = &self.samples[chan][..nsamples];
316 for &s in samp[1..].iter() {
328 bw.write0(); // no wasted bits
329 for &el in samp.iter() {
330 bw.write_s(el, samp_bits);
333 -1 | -2 | -3 | -4 => {
334 let order = -self.order as usize;
336 apply_fixed_filter(&mut self.tmp, samp, self.order);
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);
343 encode_residual(bw, &self.tmp[order..nsamples]);
346 let order = self.order as usize;
347 calc_lpc_filter(samp, &mut self.ffilter[..order]);
349 let mut filter_prec = 12;
350 let scale = f64::from(1 << filter_prec);
352 let maxval = (self.ffilter[..order].iter().fold(0.0, |acc: f64, &el| acc.max(el.abs())) * scale) as i32;
354 for (dst, &src) in self.ifilter[..order].iter_mut().zip(&self.ffilter) {
355 *dst = (src * scale) as i32;
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;
365 filter_prec -= zbits;
367 for el in self.ifilter[..order].iter_mut() {
372 apply_lpc(&mut self.tmp, samp, &self.ifilter[..order], filter_prec as u8);
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);
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);
384 encode_residual(bw, &self.tmp[order..nsamples]);
389 bw.write0(); // no wasted bits
390 bw.write(u32::from(s0 as u16), samp_bits);
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));
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;
410 if outinfo.block_len == 0 {
411 outinfo.block_len = DEFAULT_BLOCK_LEN;
413 outinfo.block_len = outinfo.block_len.max(2).min(65535);
414 let mut ofmt = *encinfo;
415 ofmt.format = NACodecTypeInfo::Audio(outinfo);
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);
428 if ainfo.block_len == 0 {
429 self.block_len = DEFAULT_BLOCK_LEN;
431 if ainfo.block_len < 2 || ainfo.block_len > 65535 {
432 return Err(EncoderError::FormatError);
434 self.block_len = ainfo.block_len;
436 if ainfo.channels == 0 || ainfo.channels > 8 {
437 return Err(EncoderError::FormatError);
439 self.channels = ainfo.channels as usize;
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();
448 self.stream = Some(stream.clone());
449 self.srate = ainfo.sample_rate;
451 self.samples.clear();
452 for _ in 0..self.channels {
453 self.samples.push(Vec::with_capacity(DEFAULT_BLOCK_LEN));
455 self.tmp.resize(self.block_len, 0);
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();
469 for dst in self.samples.iter_mut() {
471 for &samp in src[off..][..len].iter() {
472 dst.push(i32::from(samp));
477 for dst in self.samples.iter_mut() {
480 let mut src = src.iter();
482 for dst in self.samples.iter_mut() {
483 dst.push(i32::from(*src.next().unwrap()));
489 Err(EncoderError::InvalidParameters)
492 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
493 if let Ok(pkt) = self.encode_packet() {
499 fn flush(&mut self) -> EncoderResult<()> {
505 const ENCODER_OPTS: &[NAOptionDefinition] = &[
507 name: "order", description: "LPC order",
508 opt_type: NAOptionDefinitionType::Int(Some(-4), Some(32)) },
510 name: "block_size", description: "block size",
511 opt_type: NAOptionDefinitionType::Int(Some(2), Some(65535)) },
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() {
522 if let NAValue::Int(val) = option.value {
523 self.order = val as i8;
527 if let NAValue::Int(val) = option.value {
528 self.block_len = val as usize;
529 self.tmp.resize(self.block_len, 0);
538 fn query_option_value(&self, name: &str) -> Option<NAValue> {
540 "order" => Some(NAValue::Int(i64::from(self.order))),
541 "block_size" => Some(NAValue::Int(self.block_len as i64)),
547 pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
548 Box::new(FLACEncoder::new())
553 use nihav_core::codecs::*;
554 use nihav_core::demuxers::*;
555 use nihav_core::muxers::*;
556 use nihav_codec_support::test::enc_video::*;
560 fn test_flac_encoder_verbatim() {
562 NAOption{name: "order", value: NAValue::Int(0)},
564 test_flac_encoder("uncompr.flac", enc_options,
565 &[0xcd9767ee, 0xf8a86d20, 0x317944aa, 0xd9044f5c]);
568 fn test_flac_encoder_fixed1() {
570 NAOption{name: "order", value: NAValue::Int(-1)},
572 test_flac_encoder("fixed1.flac", enc_options,
573 &[0xcf654f93, 0x1db0bb07, 0xbc0cd9c3, 0xf9d2cc4e]);
576 fn test_flac_encoder_fixed4() {
578 NAOption{name: "order", value: NAValue::Int(-4)},
580 test_flac_encoder("fixed1.flac", enc_options,
581 &[0xbc2fba7f, 0x6f9406ee, 0x98be1f67, 0xe2b86b2d]);
584 fn test_flac_encoder_lpc10() {
586 NAOption{name: "order", value: NAValue::Int(10)},
588 test_flac_encoder("lpc10.flac", enc_options,
589 &[0xb6736f2e, 0xb61dda7a, 0xeb4037db, 0x8ee4afb9]);
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);
602 let dec_config = DecoderTestParams {
604 in_name: "assets/LLaudio/luckynight.flac",
605 stream_type: StreamType::Audio,
609 let enc_config = EncoderTestParams {
615 let dst_ainfo = NAAudioInfo {
618 format: SND_S16_FORMAT,
621 let enc_params = EncodeParameters {
622 format: NACodecTypeInfo::Audio(dst_ainfo),
629 // test_encoding_to_file(&dec_config, &enc_config, enc_params, enc_options);
631 test_encoding_md5(&dec_config, &enc_config, enc_params, enc_options,
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
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