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().fold(0, |acc, &x| acc + x) / (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 fn nsamples_code(nsamp: usize) -> u8 {
196 fn encode_nsamples_esc(bw: &mut BitWriter, nsamp: usize, code: u8) {
199 bw.write((nsamp - 1) as u32, 8);
202 bw.write((nsamp - 1) as u32, 16);
208 fn write_utf8(bw: &mut BitWriter, val: usize) {
209 let val = val as u32;
210 let lz = 32 - val.leading_zeros();
216 bw.write(0xC0 | (val >> 6), 8);
217 bw.write(0x80 | (val & 0x3F), 8);
220 bw.write(0xE0 | ( val >> 12), 8);
221 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
222 bw.write(0x80 | ( val & 0x3F), 8);
225 bw.write(0xF0 | ( val >> 18), 8);
226 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
227 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
228 bw.write(0x80 | ( val & 0x3F), 8);
231 bw.write(0xF8 | ( val >> 24), 8);
232 bw.write(0x80 | ((val >> 18) & 0x3F), 8);
233 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
234 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
235 bw.write(0x80 | ( val & 0x3F), 8);
238 bw.write(0xFC | ( val >> 30), 8);
239 bw.write(0x80 | ((val >> 24) & 0x3F), 8);
240 bw.write(0x80 | ((val >> 18) & 0x3F), 8);
241 bw.write(0x80 | ((val >> 12) & 0x3F), 8);
242 bw.write(0x80 | ((val >> 6) & 0x3F), 8);
243 bw.write(0x80 | ( val & 0x3F), 8);
248 const DEFAULT_BLOCK_LEN: usize = 4096;
251 fn new() -> Self { Self::default() }
252 fn encode_packet(&mut self) -> EncoderResult<NAPacket> {
253 if self.samples[0].is_empty() || (!self.flush && self.samples[0].len() < self.block_len) {
254 return Err(EncoderError::TryAgain);
257 let nsamples = self.samples[0].len().min(self.block_len);
259 let mut bw = BitWriter::new(Vec::with_capacity(1024), BitWriterMode::BE);
260 bw.write(0x3FFE, 14);
261 bw.write0(); // reserved
262 bw.write1(); // blocking strategy - variable
263 let scode = nsamples_code(nsamples);
264 bw.write(u32::from(scode), 4);
265 bw.write(0x0, 4); // sample rate - read the stream info
266 let smode = if self.channels == 2 {
267 let (l, r) = self.samples.split_at_mut(1);
268 let smode = find_stereo_mode(&l[0][..nsamples], &r[0][..nsamples]);
269 apply_stereo(&mut l[0][..nsamples], &mut r[0][..nsamples], smode);
274 let chan_idx = match smode {
275 StereoMode::Normal => (self.channels as u32) - 1,
276 StereoMode::LeftSide => 8,
277 StereoMode::SideRight => 9,
278 StereoMode::MidSide => 10,
280 bw.write(chan_idx, 4);
281 bw.write(0x4, 3); // 16 bits per sample
282 bw.write0(); // reserved
283 write_utf8(&mut bw, self.cur_pos);
284 encode_nsamples_esc(&mut bw, nsamples, scode);
285 // optional bits per sample
286 bw.write(0x00, 8); // header CRC placeholder
287 let hdr_crc_pos = bw.tell() >> 3;
288 for chan in 0..self.channels {
289 let samp_bits = match (smode, chan) {
290 (StereoMode::LeftSide, 1) |
291 (StereoMode::SideRight, 0) |
292 (StereoMode::MidSide, 1) => 16 + 1,
295 self.encode_channel(&mut bw, chan, nsamples, samp_bits);
298 let mut dbuf = bw.end();
299 calc_header_crc(&mut dbuf[..hdr_crc_pos]);
300 calc_frame_crc(&mut dbuf);
301 let ts = NATimeInfo::new(None, None, Some(nsamples as u64), 1, self.srate);
303 for samp in self.samples.iter_mut() {
304 samp.drain(..nsamples);
306 self.cur_pos += nsamples;
308 Ok(NAPacket::new(self.stream.clone().unwrap(), ts, true, dbuf))
310 fn encode_channel(&mut self, bw: &mut BitWriter, chan: usize, nsamples: usize, samp_bits: u8) {
311 let samp = &self.samples[chan][..nsamples];
315 for &s in samp[1..].iter() {
327 bw.write0(); // no wasted bits
328 for &el in samp.iter() {
329 bw.write_s(i32::from(el), samp_bits);
332 -1 | -2 | -3 | -4 => {
333 let order = -self.order as usize;
335 apply_fixed_filter(&mut self.tmp, samp, self.order);
337 bw.write(8 | (order as u32), 6);
338 bw.write0(); // no wasted bits
339 for &el in samp[..order].iter() {
340 bw.write_s(i32::from(el), samp_bits);
342 encode_residual(bw, &self.tmp[order..nsamples]);
345 let order = self.order as usize;
346 calc_lpc_filter(samp, &mut self.ffilter[..order]);
348 let mut filter_prec = 12;
349 let scale = f64::from(1 << filter_prec);
351 let maxval = (self.ffilter[..order].iter().fold(0.0, |acc: f64, &el| acc.max(el.abs())) * scale) as i32;
353 for (dst, &src) in self.ifilter[..order].iter_mut().zip(&self.ffilter) {
354 *dst = (src * scale) as i32;
357 let mut zbits = mask.trailing_zeros();
358 let mut filter_bits = 33 - maxval.leading_zeros() - zbits;
359 if filter_bits > 15 {
360 let sub = filter_bits - 15;
364 filter_prec -= zbits;
366 for el in self.ifilter[..order].iter_mut() {
371 apply_lpc(&mut self.tmp, samp, &self.ifilter[..order], filter_prec as u8);
373 bw.write(0x20 | ((order - 1) as u32), 6);
374 bw.write0(); // no wasted bits
375 for &el in samp[..order].iter() {
376 bw.write_s(i32::from(el), samp_bits);
378 bw.write(filter_bits - 1, 4);
379 bw.write(filter_prec, 5);
380 for &coef in self.ifilter[..order].iter().rev() {
381 bw.write_s(coef, filter_bits as u8);
383 encode_residual(bw, &self.tmp[order..nsamples]);
388 bw.write0(); // no wasted bits
389 bw.write(u32::from(s0 as u16), samp_bits);
394 impl NAEncoder for FLACEncoder {
395 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
396 match encinfo.format {
397 NACodecTypeInfo::None => {
398 let mut ofmt = EncodeParameters::default();
399 ofmt.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 1, SND_S16_FORMAT, DEFAULT_BLOCK_LEN));
402 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
403 NACodecTypeInfo::Audio(ainfo) => {
404 let mut outinfo = ainfo;
405 outinfo.channels = outinfo.channels.max(1).min(8);
406 if outinfo.format != SND_S16P_FORMAT && outinfo.format != SND_S16_FORMAT {
407 outinfo.format = SND_S16P_FORMAT;
409 if outinfo.block_len == 0 {
410 outinfo.block_len = DEFAULT_BLOCK_LEN;
412 outinfo.block_len = outinfo.block_len.max(2).min(65535);
413 let mut ofmt = *encinfo;
414 ofmt.format = NACodecTypeInfo::Audio(outinfo);
419 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
420 match encinfo.format {
421 NACodecTypeInfo::None => Err(EncoderError::FormatError),
422 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
423 NACodecTypeInfo::Audio(ainfo) => {
424 if ainfo.format != SND_S16P_FORMAT && ainfo.format != SND_S16_FORMAT {
425 return Err(EncoderError::FormatError);
427 if ainfo.block_len == 0 {
428 self.block_len = DEFAULT_BLOCK_LEN;
430 if ainfo.block_len < 2 || ainfo.block_len > 65535 {
431 return Err(EncoderError::FormatError);
433 self.block_len = ainfo.block_len;
435 if ainfo.channels == 0 || ainfo.channels > 8 {
436 return Err(EncoderError::FormatError);
438 self.channels = ainfo.channels as usize;
440 let soniton = SND_S16P_FORMAT;
441 let out_ainfo = NAAudioInfo::new(ainfo.sample_rate, ainfo.channels, soniton, self.block_len);
442 let info = NACodecInfo::new("flac", NACodecTypeInfo::Audio(out_ainfo), None);
443 let mut stream = NAStream::new(StreamType::Audio, stream_id, info, 1, ainfo.sample_rate, 0);
444 stream.set_num(stream_id as usize);
445 let stream = stream.into_ref();
447 self.stream = Some(stream.clone());
448 self.srate = ainfo.sample_rate;
450 self.samples.clear();
451 for _ in 0..self.channels {
452 self.samples.push(Vec::with_capacity(DEFAULT_BLOCK_LEN));
454 self.tmp.resize(self.block_len, 0);
460 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
461 let buf = frm.get_buffer();
462 if let Some(ref abuf) = buf.get_abuf_i16() {
463 let src = abuf.get_data();
464 let len = abuf.get_length();
465 if abuf.get_step() == 1 {
466 let astride = abuf.get_stride();
468 for dst in self.samples.iter_mut() {
470 for &samp in src[off..][..len].iter() {
471 dst.push(i32::from(samp));
476 for dst in self.samples.iter_mut() {
479 let mut src = src.iter();
481 for dst in self.samples.iter_mut() {
482 dst.push(i32::from(*src.next().unwrap()));
488 Err(EncoderError::InvalidParameters)
491 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
492 if let Ok(pkt) = self.encode_packet() {
498 fn flush(&mut self) -> EncoderResult<()> {
504 const ENCODER_OPTS: &[NAOptionDefinition] = &[
506 name: "order", description: "LPC order",
507 opt_type: NAOptionDefinitionType::Int(Some(-4), Some(32)) },
509 name: "block_size", description: "block size",
510 opt_type: NAOptionDefinitionType::Int(Some(2), Some(65535)) },
513 impl NAOptionHandler for FLACEncoder {
514 fn get_supported_options(&self) -> &[NAOptionDefinition] { ENCODER_OPTS }
515 fn set_options(&mut self, options: &[NAOption]) {
516 for option in options.iter() {
517 for opt_def in ENCODER_OPTS.iter() {
518 if opt_def.check(option).is_ok() {
521 if let NAValue::Int(val) = option.value {
522 self.order = val as i8;
526 if let NAValue::Int(val) = option.value {
527 self.block_len = val as usize;
528 self.tmp.resize(self.block_len, 0);
537 fn query_option_value(&self, name: &str) -> Option<NAValue> {
539 "order" => Some(NAValue::Int(i64::from(self.order))),
540 "block_size" => Some(NAValue::Int(self.block_len as i64)),
546 pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
547 Box::new(FLACEncoder::new())
552 use nihav_core::codecs::*;
553 use nihav_core::demuxers::*;
554 use nihav_core::muxers::*;
555 use nihav_codec_support::test::enc_video::*;
559 fn test_flac_encoder_verbatim() {
561 NAOption{name: "order", value: NAValue::Int(0)},
563 test_flac_encoder("uncompr.flac", enc_options,
564 &[0xcd9767ee, 0xf8a86d20, 0x317944aa, 0xd9044f5c]);
567 fn test_flac_encoder_fixed1() {
569 NAOption{name: "order", value: NAValue::Int(-1)},
571 test_flac_encoder("fixed1.flac", enc_options,
572 &[0xcf654f93, 0x1db0bb07, 0xbc0cd9c3, 0xf9d2cc4e]);
575 fn test_flac_encoder_fixed4() {
577 NAOption{name: "order", value: NAValue::Int(-4)},
579 test_flac_encoder("fixed1.flac", enc_options,
580 &[0xbc2fba7f, 0x6f9406ee, 0x98be1f67, 0xe2b86b2d]);
583 fn test_flac_encoder_lpc10() {
585 NAOption{name: "order", value: NAValue::Int(10)},
587 test_flac_encoder("lpc10.flac", enc_options,
588 &[0xb6736f2e, 0xb61dda7a, 0xeb4037db, 0x8ee4afb9]);
591 fn test_flac_encoder(name: &'static str, enc_options: &[NAOption], hash: &[u32; 4]) {
592 let mut dmx_reg = RegisteredDemuxers::new();
593 llaudio_register_all_demuxers(&mut dmx_reg);
594 let mut dec_reg = RegisteredDecoders::new();
595 llaudio_register_all_decoders(&mut dec_reg);
596 let mut mux_reg = RegisteredMuxers::new();
597 llaudio_register_all_muxers(&mut mux_reg);
598 let mut enc_reg = RegisteredEncoders::new();
599 llaudio_register_all_encoders(&mut enc_reg);
601 let dec_config = DecoderTestParams {
603 in_name: "assets/LLaudio/luckynight.flac",
604 stream_type: StreamType::Audio,
608 let enc_config = EncoderTestParams {
614 let dst_ainfo = NAAudioInfo {
617 format: SND_S16_FORMAT,
620 let enc_params = EncodeParameters {
621 format: NACodecTypeInfo::Audio(dst_ainfo),
628 // test_encoding_to_file(&dec_config, &enc_config, enc_params, enc_options);
630 test_encoding_md5(&dec_config, &enc_config, enc_params, enc_options,
635 const CRC8_TABLE: [u8; 256] = [
636 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
637 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
638 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
639 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
640 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
641 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
642 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
643 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
644 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
645 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
646 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
647 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
648 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
649 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
650 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
651 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
652 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
653 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
654 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
655 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
656 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
657 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
658 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
659 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
660 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
661 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
662 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
663 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
664 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
665 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
666 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
667 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
670 const CRC16_TABLE: [u16; 256] = [
671 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
672 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
673 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
674 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
675 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
676 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
677 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
678 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
679 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
680 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
681 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
682 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
683 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
684 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
685 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
686 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
687 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
688 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
689 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
690 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
691 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
692 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
693 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
694 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
695 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
696 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
697 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
698 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
699 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
700 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
701 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
702 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202