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 Ok(EncodeParameters {
400 format: NACodecTypeInfo::Audio(NAAudioInfo::new(0, 1, SND_S16_FORMAT, DEFAULT_BLOCK_LEN)),
401 ..Default::default() })
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 get_capabilities(&self) -> u64 { 0 }
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);
429 if ainfo.block_len == 0 {
430 self.block_len = DEFAULT_BLOCK_LEN;
432 if ainfo.block_len < 2 || ainfo.block_len > 65535 {
433 return Err(EncoderError::FormatError);
435 self.block_len = ainfo.block_len;
437 if ainfo.channels == 0 || ainfo.channels > 8 {
438 return Err(EncoderError::FormatError);
440 self.channels = ainfo.channels as usize;
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();
449 self.stream = Some(stream.clone());
450 self.srate = ainfo.sample_rate;
452 self.samples.clear();
453 for _ in 0..self.channels {
454 self.samples.push(Vec::with_capacity(DEFAULT_BLOCK_LEN));
456 self.tmp.resize(self.block_len, 0);
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();
470 for dst in self.samples.iter_mut() {
472 for &samp in src[off..][..len].iter() {
473 dst.push(i32::from(samp));
478 for dst in self.samples.iter_mut() {
481 let mut src = src.iter();
483 for dst in self.samples.iter_mut() {
484 dst.push(i32::from(*src.next().unwrap()));
490 Err(EncoderError::InvalidParameters)
493 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
494 if let Ok(pkt) = self.encode_packet() {
500 fn flush(&mut self) -> EncoderResult<()> {
506 const ENCODER_OPTS: &[NAOptionDefinition] = &[
508 name: "order", description: "LPC order",
509 opt_type: NAOptionDefinitionType::Int(Some(-4), Some(32)) },
511 name: "block_size", description: "block size",
512 opt_type: NAOptionDefinitionType::Int(Some(2), Some(65535)) },
515 impl 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() {
523 if let NAValue::Int(val) = option.value {
524 self.order = val as i8;
528 if let NAValue::Int(val) = option.value {
529 self.block_len = val as usize;
530 self.tmp.resize(self.block_len, 0);
539 fn query_option_value(&self, name: &str) -> Option<NAValue> {
541 "order" => Some(NAValue::Int(i64::from(self.order))),
542 "block_size" => Some(NAValue::Int(self.block_len as i64)),
548 pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
549 Box::new(FLACEncoder::new())
554 use nihav_core::codecs::*;
555 use nihav_core::demuxers::*;
556 use nihav_core::muxers::*;
557 use nihav_codec_support::test::enc_video::*;
561 fn test_flac_encoder_verbatim() {
563 NAOption{name: "order", value: NAValue::Int(0)},
565 test_flac_encoder("uncompr.flac", enc_options,
566 &[0xcd9767ee, 0xf8a86d20, 0x317944aa, 0xd9044f5c]);
569 fn test_flac_encoder_fixed1() {
571 NAOption{name: "order", value: NAValue::Int(-1)},
573 test_flac_encoder("fixed1.flac", enc_options,
574 &[0xcf654f93, 0x1db0bb07, 0xbc0cd9c3, 0xf9d2cc4e]);
577 fn test_flac_encoder_fixed4() {
579 NAOption{name: "order", value: NAValue::Int(-4)},
581 test_flac_encoder("fixed1.flac", enc_options,
582 &[0xbc2fba7f, 0x6f9406ee, 0x98be1f67, 0xe2b86b2d]);
585 fn test_flac_encoder_lpc10() {
587 NAOption{name: "order", value: NAValue::Int(10)},
589 test_flac_encoder("lpc10.flac", enc_options,
590 &[0xb6736f2e, 0xb61dda7a, 0xeb4037db, 0x8ee4afb9]);
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);
603 // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
604 let dec_config = DecoderTestParams {
606 in_name: "assets/LLaudio/luckynight.flac",
607 stream_type: StreamType::Audio,
611 let enc_config = EncoderTestParams {
617 let dst_ainfo = NAAudioInfo {
620 format: SND_S16_FORMAT,
623 let enc_params = EncodeParameters {
624 format: NACodecTypeInfo::Audio(dst_ainfo),
631 // test_encoding_to_file(&dec_config, &enc_config, enc_params, enc_options);
633 test_encoding_md5(&dec_config, &enc_config, enc_params, enc_options,
638 const 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
673 const 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