| 1 | use nihav_core::codecs::*; |
| 2 | use nihav_core::io::byteio::*; |
| 3 | use nihav_core::io::bitreader::*; |
| 4 | use nihav_core::io::codebook::*; |
| 5 | use nihav_codec_support::dsp::fft::*; |
| 6 | use super::qdmcommon::*; |
| 7 | |
| 8 | const MAX_NOISE_BANDS: usize = 19; |
| 9 | const MAX_FRAME_SIZE: usize = 8192; |
| 10 | |
| 11 | struct QdmcDecoder { |
| 12 | ainfo: NAAudioInfo, |
| 13 | chmap: NAChannelMap, |
| 14 | noise_val_cb: Codebook<u8>, |
| 15 | noise_seg_cb: Codebook<u8>, |
| 16 | amp_cb: Codebook<u8>, |
| 17 | amp_diff_cb: Codebook<u8>, |
| 18 | freq_diff_cb: Codebook<u8>, |
| 19 | phase_diff_cb: Codebook<u8>, |
| 20 | sin_tab: [f32; 512], |
| 21 | tone_tab: [[f32; 32]; 5], |
| 22 | rng: RNG, |
| 23 | fft: FFT, |
| 24 | fft_buf: [[FFTComplex; MAX_FRAME_SIZE * 2]; 2], |
| 25 | noise_tab: [[f32; 256]; MAX_NOISE_BANDS], |
| 26 | tmp: [f32; MAX_FRAME_SIZE], |
| 27 | sbuf: [FFTComplex; 512], |
| 28 | delay: [[f32; 512]; 2], |
| 29 | |
| 30 | noise: [[[u8; 16]; MAX_NOISE_BANDS]; 2], |
| 31 | tones: [Vec<Tone>; 5], |
| 32 | |
| 33 | order: u8, |
| 34 | frame_bits: u8, |
| 35 | samples: usize, |
| 36 | frm_bytes: usize, |
| 37 | noise_cat: usize, |
| 38 | sf_len: usize, |
| 39 | } |
| 40 | |
| 41 | fn def_cb_map(idx: usize) -> u8 { idx as u8 } |
| 42 | fn noise_val_cb_map(idx: usize) -> u8 { NOISE_VAL_SYMS[idx] } |
| 43 | fn noise_seg_cb_map(idx: usize) -> u8 { NOISE_SEG_SYMS[idx] } |
| 44 | |
| 45 | impl QdmcDecoder { |
| 46 | fn new() -> Self { |
| 47 | let mut cbr = TableCodebookDescReader::new(&NOISE_VAL_CODES, &NOISE_VAL_BITS, noise_val_cb_map); |
| 48 | let noise_val_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 49 | let mut cbr = TableCodebookDescReader::new(&NOISE_SEG_CODES, &NOISE_SEG_BITS, noise_seg_cb_map); |
| 50 | let noise_seg_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 51 | let mut cbr = TableCodebookDescReader::new(&FREQ_DIFF_CODES, &FREQ_DIFF_BITS, def_cb_map); |
| 52 | let freq_diff_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 53 | let mut cbr = TableCodebookDescReader::new(&_CODES, &_BITS, def_cb_map); |
| 54 | let amp_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 55 | let mut cbr = TableCodebookDescReader::new(&_DIFF_CODES, &_DIFF_BITS, def_cb_map); |
| 56 | let amp_diff_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 57 | let mut cbr = TableCodebookDescReader::new(&PHASE_DIFF_CODES, &PHASE_DIFF_BITS, def_cb_map); |
| 58 | let phase_diff_cb = Codebook::new(&mut cbr, CodebookMode::LSB).unwrap(); |
| 59 | |
| 60 | let mut sin_tab = [0.0f32; 512]; |
| 61 | for (i, tab) in sin_tab.iter_mut().enumerate() { |
| 62 | *tab = (2.0 * (i as f32) * std::f32::consts::PI / 512.0).sin(); |
| 63 | } |
| 64 | |
| 65 | let mut tone_tab = [[0.0; 32]; 5]; |
| 66 | for group in 0..5 { |
| 67 | for i in 0..(1 << (5 - group)) { |
| 68 | tone_tab[group][i] = sin_tab[((i + 1) << (group + 3)) & 0x1FF]; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | Self { |
| 73 | ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, 1), |
| 74 | chmap: NAChannelMap::new(), |
| 75 | noise_val_cb, noise_seg_cb, freq_diff_cb, amp_cb, amp_diff_cb, phase_diff_cb, |
| 76 | sin_tab, tone_tab, |
| 77 | noise: [[[0; 16]; MAX_NOISE_BANDS]; 2], |
| 78 | tones: [Vec::with_capacity(MAX_TONES), |
| 79 | Vec::with_capacity(MAX_TONES), |
| 80 | Vec::with_capacity(MAX_TONES), |
| 81 | Vec::with_capacity(MAX_TONES), |
| 82 | Vec::with_capacity(MAX_TONES)], |
| 83 | rng: RNG::new(), |
| 84 | fft: FFTBuilder::new_fft(256, false), |
| 85 | fft_buf: [[FFTC_ZERO; MAX_FRAME_SIZE * 2]; 2], |
| 86 | noise_tab: [[0.0; 256]; MAX_NOISE_BANDS], |
| 87 | tmp: [0.0; MAX_FRAME_SIZE], |
| 88 | sbuf: [FFTC_ZERO; 512], |
| 89 | delay: [[0.0; 512]; 2], |
| 90 | |
| 91 | order: 0, |
| 92 | frame_bits: 0, |
| 93 | samples: 0, |
| 94 | frm_bytes: 0, |
| 95 | noise_cat: 0, |
| 96 | sf_len: 0, |
| 97 | } |
| 98 | } |
| 99 | fn fill_noise_table(&mut self) { |
| 100 | let noise_bands = NOISE_SUBBANDS[self.noise_cat]; |
| 101 | self.noise_tab = [[0.0; 256]; MAX_NOISE_BANDS]; |
| 102 | for band in 0..(noise_bands.len() - 2) { |
| 103 | let prev = noise_bands[band]; |
| 104 | let cur = noise_bands[band + 1]; |
| 105 | let next = noise_bands[band + 2]; |
| 106 | |
| 107 | let noise = &mut self.noise_tab[band]; |
| 108 | for i in prev..cur { |
| 109 | noise[i] = ((i - prev) as f32) / ((cur - prev) as f32); |
| 110 | } |
| 111 | for i in cur..next { |
| 112 | noise[i] = ((next - i) as f32) / ((next - cur) as f32); |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | fn read_noise_data(&mut self, br: &mut BitReader, ch: usize) -> DecoderResult<()> { |
| 117 | let noise_bands = NOISE_SUBBANDS[self.noise_cat]; |
| 118 | for band in 0..(noise_bands.len() - 2) { |
| 119 | let val = br.read_code(&self.noise_val_cb)? as i32; |
| 120 | let mut last = to_signed(val); |
| 121 | validate!(last >= 0); |
| 122 | self.noise[ch][band][0] = last as u8; |
| 123 | let mut idx = 1; |
| 124 | while idx < 16 { |
| 125 | let len = (br.read_code_long(&self.noise_seg_cb)? as usize) + 1; |
| 126 | let val = br.read_code(&self.noise_val_cb)? as i32; |
| 127 | let val = to_signed(val) + last; |
| 128 | validate!(val >= 0); |
| 129 | validate!(len + idx <= 16); |
| 130 | for i in 1..=len { |
| 131 | self.noise[ch][band][idx] = (last + (i as i32) * (val - last) / (len as i32) - 1) as u8; |
| 132 | idx += 1; |
| 133 | } |
| 134 | last = val; |
| 135 | } |
| 136 | } |
| 137 | Ok(()) |
| 138 | } |
| 139 | fn read_wave_data(&mut self, br: &mut BitReader) -> DecoderResult<()> { |
| 140 | for tone in self.tones.iter_mut() { |
| 141 | tone.clear(); |
| 142 | } |
| 143 | for group in 0..5 { |
| 144 | let group_size = 1 << (self.frame_bits - group - 1); |
| 145 | let group_bits = 4 - group; |
| 146 | let mut freq = 1; |
| 147 | let mut off = 0; |
| 148 | let mut pos2 = 0; |
| 149 | while freq < group_size { |
| 150 | let diff = br.read_code_long(&self.freq_diff_cb)?; |
| 151 | freq += diff as usize; |
| 152 | while freq >= group_size - 1 { |
| 153 | freq -= group_size - 2; |
| 154 | off += 1 << group_bits; |
| 155 | pos2 += group_size; |
| 156 | } |
| 157 | if pos2 >= (1 << self.frame_bits) { |
| 158 | break; |
| 159 | } |
| 160 | let stereo_mode = if self.chmap.num_channels() > 1 { br.read(2)? as u8 } else { 0 }; |
| 161 | let amp = br.read_code(&self.amp_cb)? as u8; |
| 162 | let phase = br.read(3)? as u8; |
| 163 | let (amp2, phase2) = if (stereo_mode & 2) != 0 { |
| 164 | (br.read_code(&self.amp_diff_cb)? as u8, |
| 165 | br.read_code(&self.phase_diff_cb)? as u8) |
| 166 | } else { (0, 0) }; |
| 167 | if (freq >> group_bits) + 1 < self.sf_len { |
| 168 | validate!(self.tones[group as usize].len() < MAX_TONES); |
| 169 | self.tones[group as usize].push(Tone { |
| 170 | offset: off, ch: stereo_mode & 1, phase, |
| 171 | freq: freq as u16, amp_idx: amp |
| 172 | }); |
| 173 | if (stereo_mode & 2) != 0 { |
| 174 | validate!(self.tones[group as usize].len() < MAX_TONES); |
| 175 | let phase = phase.wrapping_sub(phase2) & 7; |
| 176 | let amp_idx = amp.wrapping_sub(amp2) & 0x3F; |
| 177 | self.tones[group as usize].push(Tone { |
| 178 | offset: off, ch: !stereo_mode & 1, phase, |
| 179 | freq: freq as u16, amp_idx |
| 180 | }); |
| 181 | } |
| 182 | } |
| 183 | freq += 1; |
| 184 | } |
| 185 | } |
| 186 | Ok(()) |
| 187 | } |
| 188 | fn add_noise(&mut self, ch: usize, sf: usize) { |
| 189 | let noise_bands = NOISE_SUBBANDS[self.noise_cat]; |
| 190 | self.tmp = [0.0; MAX_FRAME_SIZE]; |
| 191 | for band in 0..(noise_bands.len() - 2) { |
| 192 | if noise_bands[band] >= self.sf_len { |
| 193 | break; |
| 194 | } |
| 195 | let scale = SCALES[(self.noise[ch][band][sf >> 1] & 0x3F) as usize] / 32768.0; |
| 196 | let start = noise_bands[band]; |
| 197 | let end = noise_bands[band + 2].min(self.sf_len); |
| 198 | let linscale = &self.noise_tab[band]; |
| 199 | for i in start..end { |
| 200 | self.tmp[i] += scale * linscale[i]; |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | for i in 2..self.sf_len - 1 { |
| 205 | let im = -self.rng.next_float() * self.tmp[i]; |
| 206 | let re = self.rng.next_float() * self.tmp[i]; |
| 207 | let noise = FFTComplex { re, im }; |
| 208 | self.fft_buf[ch][sf * self.sf_len + i] += noise; |
| 209 | self.fft_buf[ch][sf * self.sf_len + i + 1] -= noise; |
| 210 | } |
| 211 | } |
| 212 | fn add_tones(&mut self, sf: usize, start_idx: &mut [usize; 5]) { |
| 213 | for group in 0..5 { |
| 214 | let group_bits = 4 - group; |
| 215 | let group_size = (1 << (group_bits + 1)) - 1; |
| 216 | for tone in self.tones[group].iter().skip(start_idx[group]) { |
| 217 | if (tone.offset as usize) > sf { |
| 218 | break; |
| 219 | } |
| 220 | start_idx[group] += 1; |
| 221 | |
| 222 | let pos = (tone.freq >> group_bits) as usize; |
| 223 | let scale = SCALES[(tone.amp_idx & 0x3F) as usize] / 32768.0; |
| 224 | let mut phase_idx = ((tone.phase as usize) * 64).wrapping_sub((2 * pos + 1) * 128) & 0x1FF; |
| 225 | for i in 0..group_size { |
| 226 | phase_idx = phase_idx.wrapping_add((2 * (tone.freq as usize) + 1) << (7 - group_bits)); |
| 227 | let factor = scale * self.tone_tab[group][i]; |
| 228 | let re = factor * self.sin_tab[(phase_idx + 128) & 0x1FF]; |
| 229 | let im = -factor * self.sin_tab[ phase_idx & 0x1FF]; |
| 230 | let val = FFTComplex { re, im }; |
| 231 | let ch = tone.ch as usize; |
| 232 | self.fft_buf[ch][(sf + i) * self.sf_len + pos] += val; |
| 233 | self.fft_buf[ch][(sf + i) * self.sf_len + pos + 1] -= val; |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | fn synth_channel(&mut self, ch: usize, subframe: usize, dst: &mut [f32]) { |
| 239 | let sf_len = self.sf_len; |
| 240 | self.sbuf = [FFTC_ZERO; 512]; |
| 241 | self.sbuf[..sf_len].copy_from_slice(&self.fft_buf[ch][subframe * sf_len..][..sf_len]); |
| 242 | self.fft.do_fft_inplace(&mut self.sbuf); |
| 243 | dst[..sf_len].copy_from_slice(&self.delay[ch][..sf_len]); |
| 244 | for (dst, src) in dst.iter_mut().take(sf_len).zip(self.sbuf.iter()) { |
| 245 | *dst += src.re; |
| 246 | } |
| 247 | for (dst, src) in self.delay[ch].iter_mut().take(sf_len).zip(self.sbuf.iter().skip(sf_len)) { |
| 248 | *dst = src.re; |
| 249 | } |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | impl NADecoder for QdmcDecoder { |
| 254 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 255 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { |
| 256 | if let Some(edata) = info.get_extradata() { |
| 257 | validate!(edata.len() >= 36); |
| 258 | let mut mr = MemoryReader::new_read(edata.as_slice()); |
| 259 | let mut br = ByteReader::new(&mut mr); |
| 260 | let size = br.read_u32be()? as usize; |
| 261 | validate!(size >= 36 && size <= edata.len()); |
| 262 | let tag = br.read_tag()?; |
| 263 | validate!(&tag == b"QDCA"); |
| 264 | let ver = br.read_u32be()?; |
| 265 | validate!(ver == 1); |
| 266 | let channels = br.read_u32be()? as usize; |
| 267 | validate!(channels == 2 || channels == 1); |
| 268 | let srate = br.read_u32be()?; |
| 269 | let full_bitrate = br.read_u32be()?; |
| 270 | let frame_len = br.read_u32be()? as usize; |
| 271 | let packet_size = br.read_u32be()? as usize; |
| 272 | validate!(packet_size > 0 && (packet_size & (packet_size - 1)) == 0); |
| 273 | validate!(frame_len == packet_size * 32); |
| 274 | let bytes_per_frame = br.read_u32be()? as usize; |
| 275 | validate!(bytes_per_frame > 6); |
| 276 | |
| 277 | self.order = (31 - (packet_size.leading_zeros() & 31)) as u8; |
| 278 | self.frame_bits = self.order + 5; |
| 279 | self.samples = frame_len; |
| 280 | self.frm_bytes = bytes_per_frame; |
| 281 | self.sf_len = packet_size; |
| 282 | |
| 283 | let srate = if ainfo.get_sample_rate() != 0 { |
| 284 | ainfo.get_sample_rate() |
| 285 | } else { srate }; |
| 286 | self.ainfo = NAAudioInfo::new(srate, channels as u8, SND_F32P_FORMAT, 1); |
| 287 | self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap(); |
| 288 | let (mut bitrate, fbits) = if srate >= 32000 { |
| 289 | (28000, 13) |
| 290 | } else if srate >= 16000 { |
| 291 | (20000, 12) |
| 292 | } else { |
| 293 | (16000, 11) |
| 294 | }; |
| 295 | if channels == 2 { |
| 296 | bitrate += bitrate / 2; |
| 297 | } |
| 298 | let idx = ((full_bitrate * 3 + bitrate / 2) / bitrate) as usize; |
| 299 | self.noise_cat = NOISE_BAND_SELECTOR[idx.min(NOISE_BAND_SELECTOR.len() - 1)]; |
| 300 | validate!(frame_len == (1 << fbits)); |
| 301 | |
| 302 | self.fft_buf = [[FFTC_ZERO; MAX_FRAME_SIZE * 2]; 2]; |
| 303 | self.fft = FFTBuilder::new_fft(packet_size * 2, false); |
| 304 | |
| 305 | self.fill_noise_table(); |
| 306 | } else { |
| 307 | return Err(DecoderError::InvalidData); |
| 308 | } |
| 309 | |
| 310 | Ok(()) |
| 311 | } else { |
| 312 | Err(DecoderError::InvalidData) |
| 313 | } |
| 314 | } |
| 315 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 316 | let info = pkt.get_stream().get_info(); |
| 317 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { |
| 318 | let pktbuf = pkt.get_buffer(); |
| 319 | validate!(pktbuf.len() == self.frm_bytes); |
| 320 | validate!(&pktbuf[..3] == b"QMC" && pktbuf[3] == 1); |
| 321 | let checksum = u16::from(pktbuf[4]) + u16::from(pktbuf[5]) * 256; |
| 322 | let mut sum = 0xE2u16; |
| 323 | for el in pktbuf.iter().skip(6) { |
| 324 | sum = sum.wrapping_add(u16::from(*el)); |
| 325 | } |
| 326 | validate!(sum == checksum); |
| 327 | |
| 328 | let channels = self.chmap.num_channels(); |
| 329 | let abuf = alloc_audio_buffer(self.ainfo, self.samples, self.chmap.clone())?; |
| 330 | let mut adata = abuf.get_abuf_f32().unwrap(); |
| 331 | let mut off = [adata.get_offset(0), adata.get_offset(1)]; |
| 332 | let dst = adata.get_data_mut().unwrap(); |
| 333 | |
| 334 | let mut br = BitReader::new(&pktbuf[6..], BitReaderMode::LE); |
| 335 | for ch in 0..channels { |
| 336 | self.read_noise_data(&mut br, ch)?; |
| 337 | } |
| 338 | self.read_wave_data(&mut br)?; |
| 339 | |
| 340 | let mut tone_start = [0; 5]; |
| 341 | for subframe in 0..32 { |
| 342 | for ch in 0..channels { |
| 343 | self.add_noise(ch, subframe); |
| 344 | } |
| 345 | self.add_tones(subframe, &mut tone_start); |
| 346 | for ch in 0..channels { |
| 347 | self.synth_channel(ch, subframe, &mut dst[off[ch]..]); |
| 348 | off[ch] += self.sf_len; |
| 349 | } |
| 350 | } |
| 351 | for ch in 0..channels { |
| 352 | let mut chunks = self.fft_buf[ch].chunks_mut(1 << self.frame_bits); |
| 353 | let first = chunks.next().unwrap(); |
| 354 | let second = chunks.next().unwrap(); |
| 355 | first.copy_from_slice(second); |
| 356 | for el in second.iter_mut() { |
| 357 | *el = FFTC_ZERO; |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | let mut frm = NAFrame::new_from_pkt(pkt, info.replace_info(NACodecTypeInfo::Audio(self.ainfo)), abuf); |
| 362 | frm.set_duration(Some(self.samples as u64)); |
| 363 | frm.set_keyframe(false); |
| 364 | Ok(frm.into_ref()) |
| 365 | } else { |
| 366 | Err(DecoderError::InvalidData) |
| 367 | } |
| 368 | } |
| 369 | fn flush(&mut self) { |
| 370 | self.fft_buf = [[FFTC_ZERO; MAX_FRAME_SIZE * 2]; 2]; |
| 371 | self.delay = [[0.0; 512]; 2]; |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | impl NAOptionHandler for QdmcDecoder { |
| 376 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 377 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 378 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 379 | } |
| 380 | |
| 381 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
| 382 | Box::new(QdmcDecoder::new()) |
| 383 | } |
| 384 | |
| 385 | #[cfg(test)] |
| 386 | mod test { |
| 387 | use nihav_core::codecs::RegisteredDecoders; |
| 388 | use nihav_core::demuxers::RegisteredDemuxers; |
| 389 | use nihav_codec_support::test::dec_video::*; |
| 390 | use crate::qt_register_all_decoders; |
| 391 | use nihav_commonfmt::generic_register_all_demuxers; |
| 392 | #[test] |
| 393 | fn test_qdmc() { |
| 394 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 395 | generic_register_all_demuxers(&mut dmx_reg); |
| 396 | let mut dec_reg = RegisteredDecoders::new(); |
| 397 | qt_register_all_decoders(&mut dec_reg); |
| 398 | |
| 399 | // sample: https://samples.mplayerhq.hu/A-codecs/QDMC/rumcoke.mov |
| 400 | test_decoding("mov", "qdesign-music", "assets/QT/rumcoke.mov", Some(32), &dmx_reg, &dec_reg, |
| 401 | ExpectedTestResult::Decodes); |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | const NOISE_VAL_BITS: [u8; 27] = [ |
| 406 | 12, 2, 3, 2, 3, 3, 5, 5, |
| 407 | 6, 7, 7, 9, 7, 10, 9, 11, |
| 408 | 9, 9, 9, 9, 9, 9, 9, 9, |
| 409 | 10, 10, 12 |
| 410 | ]; |
| 411 | const NOISE_VAL_CODES: [u16; 27] = [ |
| 412 | 0xC7A, 0x000, 0x001, 0x003, 0x005, 0x006, 0x012, 0x00A, |
| 413 | 0x022, 0x01A, 0x002, 0x0FA, 0x03A, 0x35A, 0x1C2, 0x07A, |
| 414 | 0x1FA, 0x17A, 0x0DA, 0x142, 0x0C2, 0x042, 0x1DA, 0x05A, |
| 415 | 0x15A, 0x27A, 0x47A |
| 416 | ]; |
| 417 | const NOISE_VAL_SYMS: [u8; 27] = [ |
| 418 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
| 419 | 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36 |
| 420 | ]; |
| 421 | |
| 422 | const NOISE_SEG_BITS: [u8; 12] = [ 10, 1, 2, 4, 4, 4, 6, 7, 9, 10, 8, 5 ]; |
| 423 | const NOISE_SEG_CODES: [u16; 12] = [ |
| 424 | 0x30B, 0x000, 0x001, 0x003, 0x007, 0x00F, 0x02B, 0x04B, |
| 425 | 0x00B, 0x10B, 0x08B, 0x01B |
| 426 | ]; |
| 427 | const NOISE_SEG_SYMS: [u8; 12] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 17 ]; |
| 428 | |
| 429 | const FREQ_DIFF_BITS: [u8; 47] = [ |
| 430 | 18, 2, 4, 4, 5, 4, 4, 5, 5, 4, 5, 5, 5, 5, 6, 6, |
| 431 | 6, 6, 6, 7, 7, 6, 7, 6, 6, 6, 7, 7, 7, 7, 7, 8, |
| 432 | 9, 9, 8, 9, 11, 11, 12, 12, 13, 12, 14, 15, 18, 16, 17 |
| 433 | ]; |
| 434 | const FREQ_DIFF_CODES: [u32; 47] = [ |
| 435 | 0x2AD46, 0x00001, 0x00000, 0x00003, 0x0000C, 0x0000A, 0x00007, 0x00018, |
| 436 | 0x00012, 0x0000E, 0x00004, 0x00016, 0x0000F, 0x0001C, 0x00008, 0x00022, |
| 437 | 0x00026, 0x00002, 0x0003B, 0x00034, 0x00074, 0x0001F, 0x00014, 0x0002B, |
| 438 | 0x0001B, 0x0003F, 0x00028, 0x00054, 0x00006, 0x0004B, 0x0000B, 0x00068, |
| 439 | 0x000E8, 0x00046, 0x000C6, 0x001E8, 0x00146, 0x00346, 0x00546, 0x00746, |
| 440 | 0x01D46, 0x00F46, 0x00D46, 0x06D46, 0x0AD46, 0x02D46, 0x1AD46 |
| 441 | ]; |
| 442 | |
| 443 | const AMP_BITS: [u8; 28] = [ |
| 444 | 13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, |
| 445 | 3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13 |
| 446 | ]; |
| 447 | const AMP_CODES: [u16; 28] = [ |
| 448 | 0x1EC6, 0x0006, 0x00C2, 0x0142, 0x0242, 0x0246, 0x00C6, 0x0046, |
| 449 | 0x0042, 0x0146, 0x00A2, 0x0062, 0x0026, 0x0016, 0x000E, 0x0005, |
| 450 | 0x0004, 0x0003, 0x0000, 0x0001, 0x000A, 0x0012, 0x0002, 0x0022, |
| 451 | 0x01C6, 0x02C6, 0x06C6, 0x0EC6 |
| 452 | ]; |
| 453 | |
| 454 | const AMP_DIFF_BITS: [u8; 9] = [ 8, 2, 1, 3, 4, 5, 6, 7, 8 ]; |
| 455 | const AMP_DIFF_CODES: [u8; 9] = [ |
| 456 | 0xFE, 0x00, 0x01, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x7E |
| 457 | ]; |
| 458 | |
| 459 | const PHASE_DIFF_BITS: [u8; 9] = [ 6, 2, 2, 4, 4, 6, 5, 4, 2 ]; |
| 460 | const PHASE_DIFF_CODES: [u8; 9] = [ |
| 461 | 0x35, 0x02, 0x00, 0x01, 0x0D, 0x15, 0x05, 0x09, 0x03 |
| 462 | ]; |
| 463 | |
| 464 | const NOISE_BAND_SELECTOR: [usize; 5] = [ 4, 3, 2, 1, 0 ]; |
| 465 | const NOISE_SUBBANDS: [&[usize]; 5] = [ |
| 466 | &[ 0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 56, 64, 80, 96, 120, 144, 176, 208, 240, 256 ], |
| 467 | &[ 0, 2, 4, 8, 16, 24, 32, 48, 56, 64, 80, 104, 128, 160, 208, 256 ], |
| 468 | &[ 0, 2, 4, 8, 16, 32, 48, 64, 80, 112, 160, 208, 256 ], |
| 469 | &[ 0, 4, 8, 16, 32, 48, 64, 96, 144, 208, 256 ], |
| 470 | &[ 0, 4, 16, 32, 64, 256 ] |
| 471 | ]; |
| 472 | |
| 473 | const SCALES: [f32; 64] = [ |
| 474 | 1.1875, 1.6835938, 2.375, 3.3671875, 4.75, 6.734375, 9.5, 13.46875, |
| 475 | 19.0, 26.9375, 38.0, 53.875, 76.0, 107.75, 152.0, 215.5, |
| 476 | 304.0, 431.0, 608.0, 862.0, 1216.0, 1724.0, 2432.0, 3448.0, |
| 477 | 4864.0, 6896.0, 9728.0, 13792.0, 19456.0, 27584.0, 38912.0, 55168.0, |
| 478 | 77824.0, 110336.0, 155648.0, 220672.0, 311296.0, 441344.0, 622592.0, 882688.0, |
| 479 | 1245184.0, 1765376.0, 2490368.0, 3530752.0, 4980736.0, 7061504.0, 0.0, 0.0, |
| 480 | 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, |
| 481 | 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 |
| 482 | ]; |