From 87927c5732b39bb23209486bed8d7bb7fc56b92e Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Mon, 31 Aug 2020 16:08:57 +0200 Subject: [PATCH] add nihav-llaudio crate with FLAC, Monkey's Audio, TTA and WavPack support --- nihav-allstuff/Cargo.toml | 1 + nihav-allstuff/src/lib.rs | 6 + nihav-llaudio/Cargo.toml | 29 + nihav-llaudio/src/codecs/ape.rs | 363 ++++++++ nihav-llaudio/src/codecs/apepred.rs | 472 ++++++++++ nihav-llaudio/src/codecs/apereader.rs | 489 ++++++++++ nihav-llaudio/src/codecs/flac.rs | 527 +++++++++++ nihav-llaudio/src/codecs/mod.rs | 39 + nihav-llaudio/src/codecs/tta.rs | 415 +++++++++ nihav-llaudio/src/codecs/wavpack.rs | 1195 +++++++++++++++++++++++++ nihav-llaudio/src/demuxers/ape.rs | 267 ++++++ nihav-llaudio/src/demuxers/flac.rs | 242 +++++ nihav-llaudio/src/demuxers/mod.rs | 33 + nihav-llaudio/src/demuxers/tta.rs | 140 +++ nihav-llaudio/src/demuxers/wavpack.rs | 296 ++++++ nihav-llaudio/src/lib.rs | 10 + nihav-registry/src/detect.rs | 22 + nihav-registry/src/register.rs | 9 + 18 files changed, 4555 insertions(+) create mode 100644 nihav-llaudio/Cargo.toml create mode 100644 nihav-llaudio/src/codecs/ape.rs create mode 100644 nihav-llaudio/src/codecs/apepred.rs create mode 100644 nihav-llaudio/src/codecs/apereader.rs create mode 100644 nihav-llaudio/src/codecs/flac.rs create mode 100644 nihav-llaudio/src/codecs/mod.rs create mode 100644 nihav-llaudio/src/codecs/tta.rs create mode 100644 nihav-llaudio/src/codecs/wavpack.rs create mode 100644 nihav-llaudio/src/demuxers/ape.rs create mode 100644 nihav-llaudio/src/demuxers/flac.rs create mode 100644 nihav-llaudio/src/demuxers/mod.rs create mode 100644 nihav-llaudio/src/demuxers/tta.rs create mode 100644 nihav-llaudio/src/demuxers/wavpack.rs create mode 100644 nihav-llaudio/src/lib.rs diff --git a/nihav-allstuff/Cargo.toml b/nihav-allstuff/Cargo.toml index 6c5de36..fc78a05 100644 --- a/nihav-allstuff/Cargo.toml +++ b/nihav-allstuff/Cargo.toml @@ -10,6 +10,7 @@ nihav_commonfmt = { path = "../nihav-commonfmt" } nihav_duck = { path = "../nihav-duck" } nihav_game = { path = "../nihav-game" } nihav_indeo = { path = "../nihav-indeo" } +nihav_llaudio = { path = "../nihav-llaudio" } nihav_ms = { path = "../nihav-ms" } nihav_qt = { path = "../nihav-qt" } nihav_rad = { path = "../nihav-rad" } diff --git a/nihav-allstuff/src/lib.rs b/nihav-allstuff/src/lib.rs index 5ef4fe9..90a7766 100644 --- a/nihav-allstuff/src/lib.rs +++ b/nihav-allstuff/src/lib.rs @@ -4,6 +4,7 @@ extern crate nihav_commonfmt; extern crate nihav_duck; extern crate nihav_game; extern crate nihav_indeo; +extern crate nihav_llaudio; extern crate nihav_ms; extern crate nihav_rad; extern crate nihav_realmedia; @@ -25,6 +26,9 @@ use nihav_game::game_register_all_demuxers; use nihav_indeo::indeo_register_all_decoders; +use nihav_llaudio::llaudio_register_all_decoders; +use nihav_llaudio::llaudio_register_all_demuxers; + use nihav_ms::ms_register_all_decoders; use nihav_ms::ms_register_all_encoders; @@ -42,6 +46,7 @@ pub fn nihav_register_all_decoders(rd: &mut RegisteredDecoders) { duck_register_all_decoders(rd); game_register_all_decoders(rd); indeo_register_all_decoders(rd); + llaudio_register_all_decoders(rd); ms_register_all_decoders(rd); qt_register_all_decoders(rd); rad_register_all_decoders(rd); @@ -52,6 +57,7 @@ pub fn nihav_register_all_decoders(rd: &mut RegisteredDecoders) { pub fn nihav_register_all_demuxers(rd: &mut RegisteredDemuxers) { generic_register_all_demuxers(rd); game_register_all_demuxers(rd); + llaudio_register_all_demuxers(rd); rad_register_all_demuxers(rd); realmedia_register_all_demuxers(rd); } diff --git a/nihav-llaudio/Cargo.toml b/nihav-llaudio/Cargo.toml new file mode 100644 index 0000000..229c018 --- /dev/null +++ b/nihav-llaudio/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "nihav_llaudio" +version = "0.1.0" +authors = ["Kostya Shishkov "] +edition = "2018" + +[dependencies.nihav_core] +path = "../nihav-core" +features = [] + +[dependencies.nihav_codec_support] +path = "../nihav-codec-support" + +[features] +default = ["all_decoders", "all_demuxers"] + +all_decoders = ["decoder_ape", "decoder_flac", "decoder_tta", "decoder_wavpack"] +decoders = [] +decoder_ape = ["decoders"] +decoder_flac = ["decoders"] +decoder_tta = ["decoders"] +decoder_wavpack = ["decoders"] + +all_demuxers = ["demuxer_ape", "demuxer_flac", "demuxer_tta", "demuxer_wavpack"] +demuxers = [] +demuxer_ape = ["demuxers"] +demuxer_flac = ["demuxers"] +demuxer_tta = ["demuxers"] +demuxer_wavpack = ["demuxers"] diff --git a/nihav-llaudio/src/codecs/ape.rs b/nihav-llaudio/src/codecs/ape.rs new file mode 100644 index 0000000..a89f0c5 --- /dev/null +++ b/nihav-llaudio/src/codecs/ape.rs @@ -0,0 +1,363 @@ +use nihav_core::codecs::*; +use nihav_core::io::byteio::*; +use nihav_core::io::bitreader::*; + +use super::apepred::*; +use super::apereader::*; + +struct APEDecoder { + ainfo: NAAudioInfo, + chmap: NAChannelMap, + version: u16, + decode_mono: fn(&mut Coder, &mut [i32]) -> DecoderResult<()>, + decode_stereo: fn(&mut Coder, &mut [i32], &mut [i32]) -> DecoderResult<()>, + is_stereo: bool, + left: Vec, + right: Vec, + fmode: FilterMode, + data: Vec, + blocksperframe: usize, +} + +impl APEDecoder { + fn new() -> Self { + Self { + ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), + chmap: NAChannelMap::new(), + version: 0, + decode_mono: decode_mono_dummy, + decode_stereo: decode_stereo_dummy, + is_stereo: false, + left: Vec::new(), + right: Vec::new(), + fmode: FilterMode::None, + data: Vec::new(), + blocksperframe: 0, + } + } +} + +impl NADecoder for APEDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + if let Some(buf) = info.get_extradata() { + let mut mr = MemoryReader::new_read(&buf); + let mut br = ByteReader::new(&mut mr); + let version = br.read_u16le()?; + let compression = br.read_u16le()?; + let _flags = br.read_u16le()?; + let channels = br.read_byte()?; + let bits = br.read_byte()?; + let srate = br.read_u32le()?; + let blocksperframe = br.read_u32le()? as usize; + + validate!(channels > 0); + validate!(bits > 0 && bits <= 32); + validate!((compression % 1000) == 0 && compression > 0 && compression <= 5000); + validate!(compression < 5000 || version >= 3930); + if bits != 16 { + return Err(DecoderError::NotImplemented); + } + if version > 3990 { + return Err(DecoderError::NotImplemented); + } + + self.version = version; + self.blocksperframe = blocksperframe; + self.is_stereo = channels == 2; + self.left.resize(blocksperframe, 0); + if self.is_stereo { + self.right.resize(blocksperframe, 0); + } + + self.decode_mono = if version >= 3990 { + decode_mono_3990 + } else if version >= 3910 { + decode_mono_3910 + } else if version >= 3900 { + decode_mono_3900 + } else if version >= 3890 { + decode_mono_3890 + } else if version >= 3860 { + decode_mono_3860 + } else { + decode_mono_0000 + }; + self.decode_stereo = if version >= 3990 { + decode_stereo_3990 + } else if version >= 3930 { + decode_stereo_3930 + } else if version >= 3910 { + decode_stereo_3910 + } else if version >= 3900 { + decode_stereo_3900 + } else if version >= 3890 { + decode_stereo_3890 + } else if version >= 3860 { + decode_stereo_3860 + } else { + decode_stereo_0000 + }; + self.fmode = FilterMode::new(version, compression); + + self.chmap = if channels == 1 { + NAChannelMap::from_str("C").unwrap() + } else if channels == 2 { + NAChannelMap::from_str("L,R").unwrap() + } else { + return Err(DecoderError::NotImplemented); + }; + self.ainfo = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 4602); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + if let NACodecTypeInfo::Audio(_) = info.get_properties() { + let pktbuf = pkt.get_buffer(); + validate!(pktbuf.len() > 9); + + let nblocks = read_u32le(&pktbuf[0..])? as usize; + validate!(nblocks > 0); + let bits = u32::from(pktbuf[4]); + validate!(bits < 32); + self.data.truncate(0); + self.data.reserve((pktbuf.len() & !3) + 2); + for word in pktbuf[8..].chunks_exact(4) { + self.data.push(word[3]); + self.data.push(word[2]); + self.data.push(word[1]); + self.data.push(word[0]); + } + if self.version < 3950 { + self.data.push(0); + self.data.push(0); + } + + let (mut coder, ref_crc, fflags) = if self.version < 3900 { + let mut br = BitReader::new(&self.data, BitReaderMode::BE); + br.skip(bits)?; + let mut crc = br.read(32)?; + let fflags = if self.version >= 3830 && (crc & 0x80000000) != 0 { + crc ^= 0x80000000; + br.read(32)? + } else { + 0 + }; + (Coder::Rice(RiceCoder::new(br)), crc, fflags) + } else { + let mut boff = (bits / 8) as usize; + let mut crc = read_u32be(&self.data[boff..])?; + boff += 4; + let fflags = if (crc & 0x80000000) != 0 { + crc ^= 0x80000000; + let flg = read_u32be(&self.data[boff..])?; + boff += 4; + flg + } else { + 0 + }; + // it ignores first byte anyway + (Coder::Range(RangeCoder::new(&self.data[boff + 1..])), crc, fflags) + }; + self.left.resize(nblocks, 0); + if self.is_stereo { + self.right.resize(nblocks, 0); + } + if (fflags & 3) == 0 { + if !self.is_stereo || (fflags & 4) != 0 { + (self.decode_mono)(&mut coder, &mut self.left)?; + self.fmode.filter_mono(&mut self.left); + + if (fflags & 4) != 0 { + self.right.copy_from_slice(&self.left); + } + } else { + (self.decode_stereo)(&mut coder, &mut self.left, &mut self.right)?; + self.fmode.filter_stereo(&mut self.left, &mut self.right); + } + } + + if self.version >= 0x3990 || nblocks == self.blocksperframe { + let mut crc = 0xFFFFFFFF; + if !self.is_stereo { + for el in self.left.iter() { + let byte1 = *el as u8; + let byte0 = (*el >> 8) as u8; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte1) as usize]; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte0) as usize]; + } + } else { + for (l, r) in self.left.iter().zip(self.right.iter()) { + let byte1 = *l as u8; + let byte0 = (*l >> 8) as u8; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte1) as usize]; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte0) as usize]; + let byte1 = *r as u8; + let byte0 = (*r >> 8) as u8; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte1) as usize]; + crc = (crc >> 8) ^ CRC32_TAB[((crc as u8) ^ byte0) as usize]; + } + } + crc = !crc; + if self.version >= 3830 { + crc >>= 1; + } + if crc != ref_crc { + return Err(DecoderError::ChecksumError); + } + } + + let abuf = alloc_audio_buffer(self.ainfo, nblocks, self.chmap.clone())?; + let mut adata = abuf.get_abuf_i16().unwrap(); + let off1 = adata.get_offset(1); + let dst = adata.get_data_mut().unwrap(); + let (left, right) = dst.split_at_mut(off1); + for (dst, src) in left.iter_mut().zip(self.left.iter()) { + *dst = *src as i16; + } + if self.is_stereo { + for (dst, src) in right.iter_mut().zip(self.right.iter()) { + *dst = *src as i16; + } + } + + let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); + frm.set_duration(Some(nblocks as u64)); + Ok(frm.into_ref()) + } else { + Err(DecoderError::InvalidData) + } + } + fn flush(&mut self) { + } +} + +impl NAOptionHandler for APEDecoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { + Box::new(APEDecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::llaudio_register_all_decoders; + use crate::llaudio_register_all_demuxers; + #[test] + fn test_ape_3990() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight.ape", Some(3), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0x569e002b, 0xd93772a9, 0x1cfd81cd, 0xad81319a])); + } + #[test] + fn test_ape_3940() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac394b1-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } + #[test] + fn test_ape_3920() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac392b2-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } + #[test] + fn test_ape_3910() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac391b1-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } + #[test] + fn test_ape_3890() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac389b1-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } + #[test] + fn test_ape_3880() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac388-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } + #[test] + fn test_ape_3800() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("ape", "ape", "assets/LLaudio/ape/luckynight-mac380-c4000.ape", Some(1), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xeb55ece6, 0xe5f22759, 0xd0696dd6, 0x84ae9a6c])); + } +} + +const CRC32_TAB: [u32; 256] = [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +]; diff --git a/nihav-llaudio/src/codecs/apepred.rs b/nihav-llaudio/src/codecs/apepred.rs new file mode 100644 index 0000000..6aad207 --- /dev/null +++ b/nihav-llaudio/src/codecs/apepred.rs @@ -0,0 +1,472 @@ +const HISTORY_SIZE: usize = 512; + +fn val2sign(val: i32) -> i32 { + if val > 0 { + -1 + } else if val < 0 { + 1 + } else { + 0 + } +} + +pub struct OldFilt { + version: u16, + compression: u16, +} + +pub struct NewFilt { + version: u16, + filters: [NFilterContext; 3], + lfilt: LastFilterContext, + rfilt: LastFilterContext, +} + +#[allow(clippy::large_enum_variant)] +pub enum FilterMode { + Old(OldFilt), + New(NewFilt), + None, +} + +impl FilterMode { + pub fn new(version: u16, compression: u16) -> Self { + if version < 3930 { + FilterMode::Old(OldFilt::new(version, compression)) + } else { + FilterMode::New(NewFilt::new(version, compression)) + } + } + pub fn filter_mono(&mut self, l: &mut [i32]) { + match *self { + FilterMode::Old(ref mut ofilt) => ofilt.filter(l), + FilterMode::New(ref mut nfilt) => nfilt.filter_mono(l), + FilterMode::None => unreachable!(), + }; + } + pub fn filter_stereo(&mut self, l: &mut [i32], r: &mut [i32]) { + match *self { + FilterMode::Old(ref mut ofilt) => { + ofilt.filter(l); + ofilt.filter(r); + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + let new_l = *l - *r / 2; + let new_r = *r + new_l; + *l = new_l; + *r = new_r; + } + }, + FilterMode::New(ref mut nfilt) => { + nfilt.filter_stereo(l, r); + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + let new_l = *r - *l / 2; + let new_r = *l + new_l; + *l = new_l; + *r = new_r; + } + }, + FilterMode::None => unreachable!(), + }; + } +} + +const NEW_FILTER_PARAMS: [[(u8, u8); 3]; 5] = [ + [ (0, 0), ( 0, 0), ( 0, 0) ], + [ (1, 11), ( 0, 0), ( 0, 0) ], + [ (4, 11), ( 0, 0), ( 0, 0) ], + [ (2, 10), (16, 13), ( 0, 0) ], + [ (1, 11), (16, 13), (80, 15) ], +]; + +#[derive(Clone,Default)] +struct NFilterContext { + buf: Vec, + coeffs: Vec, + order: usize, + bits: u8, + avg: i32, + new: bool, +} + +impl NFilterContext { + fn new(ord16: u8, bits: u8, new: bool) -> Self { + let order = ord16 as usize * 16; + Self { + buf: if order > 0 { vec![0; order * 2 + HISTORY_SIZE] } else { Vec::new() }, + coeffs: vec![0; order], + order, + bits, + avg: 0, + new, + } + } + fn reset(&mut self) { + for el in self.buf[..self.order * 2].iter_mut() { *el = 0; } + for el in self.coeffs.iter_mut() { *el = 0; } + self.avg = 0; + } + fn apply(&mut self, dst: &mut [i32]) { + if self.order == 0 { return; } + let mut adapt_pos = self.order; + let mut delay_pos = self.order * 2; + for el in dst.iter_mut() { + let mut sum = 0i32; + for (i, coef) in self.coeffs.iter_mut().enumerate() { + sum += *coef * self.buf[delay_pos - self.order + i]; + if *el < 0 { + *coef += self.buf[adapt_pos - self.order + i]; + } else if *el > 0 { + *coef -= self.buf[adapt_pos - self.order + i]; + } + } + let pred = (sum + (1 << (self.bits - 1))) >> self.bits; + let val = *el + pred; + *el = val; + self.buf[delay_pos] = val.min(32767).max(-32768); + if self.new { + let aval = val.abs(); + let sign = val2sign(val); + self.buf[adapt_pos] = if aval == 0 { + 0 + } else if aval <= self.avg * 4 / 3 { + sign * 8 + } else if aval <= self.avg * 3 { + sign * 16 + } else { + sign * 32 + }; + self.avg += (aval - self.avg) / 16; + self.buf[adapt_pos - 1] >>= 1; + self.buf[adapt_pos - 2] >>= 1; + self.buf[adapt_pos - 8] >>= 1; + } else { + self.buf[adapt_pos] = 4 * val2sign(val); + self.buf[adapt_pos - 4] >>= 1; + self.buf[adapt_pos - 8] >>= 1; + } + delay_pos += 1; + adapt_pos += 1; + if delay_pos == HISTORY_SIZE + self.order * 2 { + delay_pos = self.order * 2; + adapt_pos = self.order; + for i in 0..self.order * 2 { + self.buf[i] = self.buf[HISTORY_SIZE + i]; + } + } + } + } +} + +#[derive(Clone,Copy,Default)] +struct LastFilterContext { + last_a: i32, + filter_a: i32, + filter_b: i32, + coeffs_a: [i32; 4], + coeffs_b: [i32; 5], + delay_a: [i32; 4], + adapt_a: [i32; 4], + delay_b: [i32; 5], + adapt_b: [i32; 5], +} + +impl LastFilterContext { + fn init(&mut self) { + const COEFFS_A_NEW: [i32; 4] = [360, 317, -109, 98]; + + self.filter_a = 0; + self.filter_b = 0; + self.coeffs_a = COEFFS_A_NEW; + self.coeffs_b = [0; 5]; + self.last_a = 0; + self.delay_a = [0; 4]; + self.adapt_a = [0; 4]; + self.delay_b = [0; 5]; + self.adapt_b = [0; 5]; + } + fn predict_a(&mut self) -> i32 { + for i in (0..3).rev() { + self.delay_a[i + 1] = self.delay_a[i]; + self.adapt_a[i + 1] = self.adapt_a[i]; + } + self.delay_a[0] = self.last_a; + self.delay_a[1] = self.last_a - self.delay_a[1]; + self.adapt_a[0] = val2sign(self.delay_a[0]); + self.adapt_a[1] = val2sign(self.delay_a[1]); + + self.delay_a[0] * self.coeffs_a[0] + + self.delay_a[1] * self.coeffs_a[1] + + self.delay_a[2] * self.coeffs_a[2] + + self.delay_a[3] * self.coeffs_a[3] + } + fn predict_b(&mut self, other_a: i32) -> i32 { + for i in (0..4).rev() { + self.delay_b[i + 1] = self.delay_b[i]; + self.adapt_b[i + 1] = self.adapt_b[i]; + } + self.delay_b[0] = other_a - ((self.filter_b * 31) >> 5); + self.delay_b[1] = self.delay_b[0] - self.delay_b[1]; + self.adapt_b[0] = val2sign(self.delay_b[0]); + self.adapt_b[1] = val2sign(self.delay_b[1]); + + self.filter_b = other_a; + + (self.delay_b[0] * self.coeffs_b[0] + + self.delay_b[1] * self.coeffs_b[1] + + self.delay_b[2] * self.coeffs_b[2] + + self.delay_b[3] * self.coeffs_b[3] + + self.delay_b[4] * self.coeffs_b[4]) >> 1 + } + fn update_a(&mut self, pred: i32, diff: i32) -> i32 { + self.last_a = diff + (pred >> 10); + let sign = val2sign(diff); + for i in 0..4 { + self.coeffs_a[i] += self.adapt_a[i] * sign; + } + self.filter_a = self.last_a + ((self.filter_a * 31) >> 5); + + self.filter_a + } + fn update_b(&mut self, diff: i32) { + let sign = val2sign(diff); + for i in 0..5 { + self.coeffs_b[i] += self.adapt_b[i] * sign; + } + } + fn predict_3930(&mut self, diff: i32) -> i32 { + for i in (0..3).rev() { + self.delay_a[i + 1] = self.delay_a[i]; + } + self.delay_a[0] = self.last_a; + let d0 = self.delay_a[0]; + let d1 = self.delay_a[0] - self.delay_a[1]; + let d2 = self.delay_a[1] - self.delay_a[2]; + let d3 = self.delay_a[2] - self.delay_a[3]; + + let pred = (self.coeffs_a[0] * d0 + + self.coeffs_a[1] * d1 + + self.coeffs_a[2] * d2 + + self.coeffs_a[3] * d3) >> 9; + self.last_a = diff + pred; + self.filter_a = self.last_a + ((self.filter_a * 31) >> 5); + + let sign = val2sign(diff); + self.coeffs_a[0] += if d0 < 0 { sign } else { -sign }; + self.coeffs_a[1] += if d1 < 0 { sign } else { -sign }; + self.coeffs_a[2] += if d2 < 0 { sign } else { -sign }; + self.coeffs_a[3] += if d3 < 0 { sign } else { -sign }; + + self.filter_a + } +} + +impl NewFilt { + fn new(version: u16, compression: u16) -> Self { + let cidx = (compression / 1000) as usize - 1; + let mut obj = Self { + version, + filters: [NFilterContext::default(), NFilterContext::default(), NFilterContext::default()], + lfilt: LastFilterContext::default(), + rfilt: LastFilterContext::default(), + }; + obj.version = version; + let new = version >= 3980; + for i in 0..3 { + let (ord16, bits) = NEW_FILTER_PARAMS[cidx][i]; + obj.filters[i] = NFilterContext::new(ord16, bits, new); + } + obj + } + fn filter_mono(&mut self, dst: &mut [i32]) { + for filt in self.filters.iter_mut() { + filt.reset(); + filt.apply(dst); + } + self.lfilt.init(); + if self.version >= 3950 { + for el in dst.iter_mut() { + let pred = self.lfilt.predict_a(); + *el = self.lfilt.update_a(pred, *el); + } + } else { + for el in dst.iter_mut() { + *el = self.lfilt.predict_3930(*el); + } + } + } + fn filter_stereo(&mut self, l: &mut [i32], r: &mut [i32]) { + for filt in self.filters.iter_mut() { + filt.reset(); + filt.apply(l); + filt.reset(); + filt.apply(r); + } + self.lfilt.init(); + self.rfilt.init(); + if self.version >= 3950 { + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + let mut pred = self.lfilt.predict_a(); + pred += self.lfilt.predict_b(self.rfilt.filter_a); + let new_l = self.lfilt.update_a(pred, *l); + self.lfilt.update_b(*l); + *l = new_l; + + let mut pred = self.rfilt.predict_a(); + pred += self.rfilt.predict_b(self.lfilt.filter_a); + let new_r = self.rfilt.update_a(pred, *r); + self.rfilt.update_b(*r); + *r = new_r; + } + } else { + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + let new_l = self.lfilt.predict_3930(*r); + let new_r = self.rfilt.predict_3930(*l); + *l = new_l; + *r = new_r; + } + } + } +} + +impl OldFilt { + fn new(version: u16, compression: u16) -> Self { + Self { + version, compression + } + } + fn filter(&mut self, dst: &mut [i32]) { + match self.compression { + 1000 => { + Self::filter_fast(dst); + }, + 2000 => { + Self::filter_normal(dst, 4, 10); + }, + 3000 => { + Self::filter_high(dst, 16, 9); + Self::filter_normal(dst, 16, 10); + }, + 4000 => { + if self.version < 3830 { + Self::filter_high(dst, 128, 11); + Self::filter_normal(dst, 128, 10); + } else { + Self::filter_extra_high(dst); + Self::filter_high(dst, 256, 12); + Self::filter_normal(dst, 256, 11); + } + }, + _ => unreachable!(), + }; + } + fn filter_fast(dst: &mut [i32]) { + const COEFF_A_FAST: i32 = 375; + + if dst.len() <= 3 { + return; + } + let mut delay = [dst[1], dst[0]]; + let mut last = dst[2]; + let mut filter = dst[2]; + let mut weight = COEFF_A_FAST; + for el in dst[3..].iter_mut() { + delay[1] = delay[0]; + delay[0] = last; + let pred = delay[0] * 2 - delay[1]; + last = *el + ((pred * weight) >> 9); + if (*el ^ pred) > 0 { + weight += 1; + } else { + weight -= 1; + } + filter += last; + *el = filter; + } + } + fn filter_normal(dst: &mut [i32], start: usize, shift: u8) { + const COEFFS_A_NORMAL: [i32; 3] = [64, 115, 64]; + const COEFFS_B_NORMAL: [i32; 2] = [740, 0]; + + let mut last = 0; + let mut coeffs_a = COEFFS_A_NORMAL; + let mut coeffs_b = COEFFS_B_NORMAL; + let mut filter_a = 0; + let mut filter_b = 0; + let mut delay_a = [0; 3]; + let mut delay_b = [0; 2]; + + for (i, el) in dst.iter_mut().enumerate() { + delay_a[2] = delay_a[1]; delay_a[1] = delay_a[0]; delay_a[0] = last; + delay_b[1] = delay_b[0]; delay_b[0] = filter_b; + if i < start { + let val = *el + filter_a; + last = *el; + filter_b = *el; + filter_a = val; + *el = val; + continue; + } + let a0 = delay_a[0] + (delay_a[2] - delay_a[1]) * 8; + let a1 = (delay_a[0] - delay_a[1]) * 2; + let a2 = delay_a[0]; + let b0 = delay_b[0] * 2 - delay_b[1]; + let b1 = delay_b[0]; + + let pred_a = a0 * coeffs_a[0] + a1 * coeffs_a[1] + a2 * coeffs_a[2]; + let pred_b = b0 * coeffs_b[0] - b1 * coeffs_b[1]; + + let sign = val2sign(*el); + coeffs_a[0] += (((a0 >> 30) & 2) - 1) * sign; + coeffs_a[1] += (((a1 >> 28) & 8) - 4) * sign; + coeffs_a[2] += (((a2 >> 28) & 8) - 4) * sign; + last = *el + (pred_a >> 11); + + let sign = val2sign(last); + coeffs_b[0] += (((b0 >> 29) & 4) - 2) * sign; + coeffs_b[1] -= (((b1 >> 30) & 2) - 1) * sign; + + filter_b = last + (pred_b >> shift); + filter_a = filter_b + ((filter_a * 31) >> 5); + + *el = filter_a; + } + } + fn filter_high(dst: &mut [i32], order: usize, shift: u8) { + let mut coeffs = [0i32; 256]; + let mut delay = [0i32; 256]; + if dst.len() <= order { + return; + } + delay[..order].copy_from_slice(&dst[..order]); + for el in dst[order..].iter_mut() { + let sign = val2sign(*el); + let mut sum = 0; + for i in 0..order { + sum += delay[i] * coeffs[i]; + coeffs[i] -= (((delay[i] >> 30) & 2) - 1) * sign; + } + *el -= sum >> shift; + for i in 0..order-1 { + delay[i] = delay[i + 1]; + } + delay[order - 1] = *el; + } + } + fn filter_extra_high(dst: &mut [i32]) { + let mut coeffs = [0i32; 8]; + let mut delay = [0i32; 8]; + for el in dst[256..].iter_mut() { + let sign = val2sign(*el); + let mut sum = 0; + for i in 0..8 { + sum += delay[i] * coeffs[i]; + coeffs[i] -= (((delay[i] >> 30) & 2) - 1) * sign; + } + for i in (0..7).rev() { + delay[i + 1] = delay[i]; + } + delay[0] = *el; + *el -= sum >> 9; + } + } +} diff --git a/nihav-llaudio/src/codecs/apereader.rs b/nihav-llaudio/src/codecs/apereader.rs new file mode 100644 index 0000000..acd602b --- /dev/null +++ b/nihav-llaudio/src/codecs/apereader.rs @@ -0,0 +1,489 @@ +use nihav_core::codecs::{DecoderError, DecoderResult}; +use nihav_core::io::bitreader::*; +use nihav_core::io::intcode::*; + +pub struct RiceParams { + k: u8, + sum: u32 +} + +impl RiceParams { + pub fn new() -> Self { + let k = 10; + Self { k, sum: 1 << (k + 4) } + } + fn update(&mut self, val: u32) { + let limit = if self.k > 0 { 1 << (self.k + 4) } else { 0 }; + self.sum -= (self.sum + 16) >> 5; + self.sum += (val + 1) / 2; + if self.sum < limit { + self.k -= 1; + } else if (self.sum >= (1 << (self.k + 5))) && (self.k < 27) { + self.k += 1; + } + } + fn update_old(&mut self, val: u32) { + let limit = if self.k > 0 { 1 << (self.k + 4) } else { 0 }; + self.sum -= (self.sum + 8) >> 4; + self.sum += val; + if self.sum < limit { + self.k -= 1; + } else if (self.sum >= (1 << (self.k + 5))) && (self.k < 24) { + self.k += 1; + } + } +} + +pub struct RiceCoder<'a> { + br: BitReader<'a>, + rice_x: RiceParams, + rice_y: RiceParams, +} + +impl<'a> RiceCoder<'a> { + pub fn new(br: BitReader<'a>) -> Self { + Self { + br, + rice_x: RiceParams::new(), + rice_y: RiceParams::new(), + } + } +} + +struct ARangeCoder<'a> { + src: &'a [u8], + pos: usize, + low: u32, + range: u32, + help: u32, + buffer: u32, + error: bool, +} + +pub struct RangeCoder<'a> { + rc: ARangeCoder<'a>, + rice_x: RiceParams, + rice_y: RiceParams, +} + +impl<'a> RangeCoder<'a> { + pub fn new(src: &'a [u8]) -> Self { + Self { + rc: ARangeCoder::new(src), + rice_x: RiceParams::new(), + rice_y: RiceParams::new(), + } + } + fn had_errors(&self) -> bool { self.rc.error } +} + +const RANGE_BITS: u8 = 32; +const TOP: u32 = 1 << (RANGE_BITS - 1); +const BOTTOM: u32 = TOP >> 8; +const START_BITS: u8 = ((RANGE_BITS - 2) & 7) + 1; + +const MAX_MODEL_VAL: u32 = 63; + +impl<'a> ARangeCoder<'a> { + fn new(src: &'a [u8]) -> Self { + let buffer = u32::from(src[0]); + Self { + src: &src[1..], + pos: 0, + low: buffer >> (8 - START_BITS), + range: 1 << START_BITS, + help: 0, + buffer, + error: false, + } + } + fn reset(&mut self) { + if self.pos == 0 { + self.error = true; + } else { + self.pos -= 1; + } + if self.pos < self.src.len() - 1 { + self.buffer = u32::from(self.src[self.pos]); + self.pos += 1; + } + self.low = self.buffer >> (8 - START_BITS); + self.range = 1 << START_BITS; + self.help = 0; + } + fn normalise(&mut self) { + while self.range <= BOTTOM { + self.buffer <<= 8; + if self.pos < self.src.len() { + self.buffer |= u32::from(self.src[self.pos]); + self.pos += 1; + } else { + self.error = true; + } + self.low <<= 8; + self.low |= (self.buffer >> 1) & 0xFF; + self.range <<= 8; + } + } + fn get_freq(&mut self, freq: u32) -> u32 { + self.normalise(); + self.help = self.range / freq; + self.low / self.help + } + fn get_bits(&mut self, bits: u8) -> u32 { + self.normalise(); + self.help = self.range >> bits; + self.low / self.help + } + fn update(&mut self, interval: u32, low: u32) { + self.low -= self.help * low; + self.range = self.help * interval; + } + fn decode_freq(&mut self, freq: u32) -> u32 { + let sym = self.get_freq(freq); + self.update(1, sym); + sym + } + fn decode_bits(&mut self, bits: u8) -> u32 { + let sym = self.get_bits(bits); + self.update(1, sym); + sym + } + fn decode_symbol(&mut self, freqs: &[u32; 22]) -> u32 { + let bits = self.get_bits(16); + if bits > 65492 { + let sym = bits + MAX_MODEL_VAL - 65535; + self.update(1, bits); + if bits > 65536 { + self.error = true; + } + sym + } else { + let mut sym = 0usize; + while freqs[sym + 1] <= bits { + sym += 1; + } + self.update(freqs[sym + 1] - freqs[sym], freqs[sym]); + sym as u32 + } + } +} + +pub enum Coder<'a> { + Rice(RiceCoder<'a>), + Range(RangeCoder<'a>), +} + +fn to_signed(val: u32) -> i32 { + if (val & 1) != 0 { + (val >> 1) as i32 + 1 + } else { + -((val >> 1) as i32) + } +} + +pub fn decode_mono_dummy(_c: &mut Coder, _l: &mut [i32]) -> DecoderResult<()> { + unreachable!(); +} +pub fn decode_stereo_dummy(_c: &mut Coder, _l: &mut [i32], _r: &mut [i32]) -> DecoderResult<()> { + unreachable!(); +} + +fn new_k(val: u32) -> u8 { + (32 - (val | 1).leading_zeros()) as u8 +} +fn rice_limit(k: u8) -> u32 { if k > 0 { 1 << (k + 4) } else { 0 } } +fn decode_channel_0000(br: &mut BitReader, dst: &mut [i32]) -> DecoderResult<()> { + let (part01, part2) = dst.split_at_mut(64); + let (part0, part1) = part01.split_at_mut(5); + let mut pos = 0; + let mut last = [0u32; 64]; + let mut sum = 0; + for el in part0.iter_mut() { + let val = br.read_code(UintCodeType::Rice(10))?; + sum += val; + *el = to_signed(val); + last[pos] = val; + pos += 1; + } + if part1.is_empty() { + return Ok(()); + } + let mut k = new_k(sum / 10); + let mut w = 12; + for el in part1.iter_mut() { + let val = br.read_code(UintCodeType::Rice(k))?; + sum += val; + *el = to_signed(val); + k = new_k(sum / w); + w += 2; + last[pos] = val; + pos += 1; + } + if part2.is_empty() { + return Ok(()); + } + let mut top_limit = rice_limit(k + 1) * 4; + let mut bot_limit = rice_limit(k) * 4; + pos = 0; + for el in part2.iter_mut() { + let val = br.read_code(UintCodeType::Rice(k))?; + *el = to_signed(val); + + sum = sum.wrapping_add(val.wrapping_sub(last[pos])); + while sum < bot_limit { + k -= 1; + bot_limit = rice_limit(k) * 4; + top_limit >>= 1; + } + while sum >= top_limit { + k += 1; + validate!(k < 24); + bot_limit = rice_limit(k) * 4; + top_limit <<= 1; + } + + last[pos] = val; + pos = (pos + 1) & 63; + } + + Ok(()) +} +pub fn decode_mono_0000(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + decode_channel_0000(&mut rr.br, l) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_0000(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + decode_channel_0000(&mut rr.br, l)?; + decode_channel_0000(&mut rr.br, r)?; + Ok(()) + } else { + Err(DecoderError::Bug) + } +} + +fn decode_value_3860(br: &mut BitReader, rice: &mut RiceParams) -> DecoderResult { + let overflow = br.read_code(UintCodeType::UnaryZeroes)?; + + let val = (overflow << rice.k) | br.read(rice.k)?; + rice.update_old(val); + Ok(to_signed(val)) +} +fn decode_value_3890(br: &mut BitReader, rice: &mut RiceParams) -> DecoderResult { + let mut overflow = br.read_code(UintCodeType::UnaryZeroes)?; + while overflow >= 16 { + overflow -= 16; + rice.k += 4; + } + + let val = (overflow << rice.k) | br.read(rice.k)?; + rice.update_old(val); + Ok(to_signed(val)) +} +pub fn decode_mono_3860(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + for el in l.iter_mut() { + *el = decode_value_3860(&mut rr.br, &mut rr.rice_y)?; + } + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_mono_3890(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + for el in l.iter_mut() { + *el = decode_value_3860(&mut rr.br, &mut rr.rice_y)?; + } + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3860(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + for el in l.iter_mut() { + *el = decode_value_3860(&mut rr.br, &mut rr.rice_y)?; + } + for el in r.iter_mut() { + *el = decode_value_3860(&mut rr.br, &mut rr.rice_x)?; + } + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3890(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Rice(ref mut rr) = c { + for el in l.iter_mut() { + *el = decode_value_3890(&mut rr.br, &mut rr.rice_y)?; + } + for el in r.iter_mut() { + *el = decode_value_3890(&mut rr.br, &mut rr.rice_x)?; + } + Ok(()) + } else { + Err(DecoderError::Bug) + } +} + +const COUNTS_3900: &[u32; 22] = &[ + 0, 14824, 28224, 39348, 47855, 53994, 58171, 60926, + 62682, 63786, 64463, 64878, 65126, 65276, 65365, 65419, + 65450, 65469, 65480, 65487, 65491, 65493 +]; +fn decode_value_3900(rc: &mut ARangeCoder, rice: &mut RiceParams) -> i32 { + let mut overflow = rc.decode_symbol(COUNTS_3900); + let k = if overflow == MAX_MODEL_VAL { + overflow = 0; + rc.decode_bits(5) as u8 + } else { + rice.k.saturating_sub(1) + }; + let base = rc.decode_bits(k); + let val = base + (overflow << k); + rice.update(val); + to_signed(val) +} +fn decode_value_3910(rc: &mut ARangeCoder, rice: &mut RiceParams) -> i32 { + let mut overflow = rc.decode_symbol(COUNTS_3900); + let k = if overflow == MAX_MODEL_VAL { + overflow = 0; + rc.decode_bits(5) as u8 + } else { + rice.k.saturating_sub(1) + }; + let base = if k <= 16 { + rc.decode_bits(k) + } else if k <= 32 { + let low = rc.decode_bits(k); + let high = rc.decode_bits(k - 16); + (high << (k - 16)) | low + } else { + rc.error = true; + return 0; + }; + let val = base + (overflow << k); + rice.update(val); + to_signed(val) +} +pub fn decode_mono_3900(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for el in l.iter_mut() { + *el = decode_value_3900(&mut rc.rc, &mut rc.rice_y); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_mono_3910(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for el in l.iter_mut() { + *el = decode_value_3910(&mut rc.rc, &mut rc.rice_y); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3900(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for el in l.iter_mut() { + *el = decode_value_3900(&mut rc.rc, &mut rc.rice_y); + } + rc.rc.normalise(); + validate!(!rc.had_errors() && rc.rc.pos < rc.rc.src.len()); + rc.rc.reset(); + for el in r.iter_mut() { + *el = decode_value_3900(&mut rc.rc, &mut rc.rice_x); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3910(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for el in l.iter_mut() { + *el = decode_value_3910(&mut rc.rc, &mut rc.rice_y); + } + rc.rc.normalise(); + validate!(!rc.had_errors() && rc.rc.pos < rc.rc.src.len()); + rc.rc.reset(); + for el in r.iter_mut() { + *el = decode_value_3910(&mut rc.rc, &mut rc.rice_x); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3930(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + *l = decode_value_3910(&mut rc.rc, &mut rc.rice_y); + *r = decode_value_3910(&mut rc.rc, &mut rc.rice_x); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} + +const COUNTS_3990: &[u32; 22] = &[ + 0, 19578, 36160, 48417, 56323, 60899, 63265, 64435, + 64971, 65232, 65351, 65416, 65447, 65466, 65476, 65482, + 65485, 65488, 65490, 65491, 65492, 65493 +]; +fn decode_value_3990(rc: &mut ARangeCoder, rice: &mut RiceParams) -> i32 { + let pivot = (rice.sum >> 5).max(1); + let mut overflow = rc.decode_symbol(COUNTS_3990); + if overflow == MAX_MODEL_VAL { + overflow = rc.decode_bits(16) << 16; + overflow |= rc.decode_bits(16); + } + let base = if pivot < (1 << 16) { + rc.decode_freq(pivot) + } else { + let shift = (16 - pivot.trailing_zeros()) as u8; + let hi = rc.decode_freq((pivot >> shift) + 1); + let lo = rc.decode_bits(shift); + (hi << shift) | lo + }; + let val = base + overflow * pivot; + rice.update(val); + to_signed(val) +} +pub fn decode_mono_3990(c: &mut Coder, l: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for el in l.iter_mut() { + *el = decode_value_3990(&mut rc.rc, &mut rc.rice_y); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} +pub fn decode_stereo_3990(c: &mut Coder, l: &mut [i32], r: &mut [i32]) -> DecoderResult<()> { + if let Coder::Range(ref mut rc) = c { + for (l, r) in l.iter_mut().zip(r.iter_mut()) { + *l = decode_value_3990(&mut rc.rc, &mut rc.rice_y); + *r = decode_value_3990(&mut rc.rc, &mut rc.rice_x); + } + validate!(!rc.had_errors()); + Ok(()) + } else { + Err(DecoderError::Bug) + } +} diff --git a/nihav-llaudio/src/codecs/flac.rs b/nihav-llaudio/src/codecs/flac.rs new file mode 100644 index 0000000..55cd6bb --- /dev/null +++ b/nihav-llaudio/src/codecs/flac.rs @@ -0,0 +1,527 @@ +use nihav_core::codecs::*; +use nihav_core::io::byteio::*; +use nihav_core::io::bitreader::*; +use nihav_core::io::intcode::*; + +const MAX_SAMPLES: usize = 32768; + +#[derive(Clone,Copy,PartialEq)] +enum StereoMode { + Normal, + LeftSide, + SideRight, + MidSide, +} + +struct FlacDecoder { + ainfo: NAAudioInfo, + chmap: NAChannelMap, + min_blk_size: usize, + max_blk_size: usize, + min_frm_size: usize, + max_frm_size: usize, + channels: u8, + bits: u8, + srate: u32, + residues: [Vec; 8], +} + +fn decode_partition(br: &mut BitReader, dst: &mut [i32], k: u8) -> DecoderResult<()> { + for el in dst.iter_mut() { + let val = br.read_code(UintCodeType::Rice(k))?; + if (val & 1) == 0 { + *el = (val >> 1) as i32; + } else { + *el = -(((val + 1) >> 1) as i32); + } + } + Ok(()) +} + +fn decode_residual(br: &mut BitReader, dst: &mut [i32], order: usize) -> DecoderResult<()> { + let mode = br.read(2)?; + validate!(mode < 2); + let rice_k = if mode == 0 { 4 } else { 5 }; + let esc = (1 << rice_k) - 1; + + let num_partitions = 1 << br.read(4)?; + let tot_size = dst.len() + order; + validate!((tot_size % num_partitions) == 0); + let psize = tot_size / num_partitions; + validate!(psize >= order); + let mut off = psize - order; + let k = br.read(rice_k)? as u8; + if k != esc { + decode_partition(br, &mut dst[..off], k)?; + } else { + let bits = br.read(5)? as u8; + for el in dst.iter_mut().take(off) { + *el = br.read_s(bits)?; + } + } + for _ in 1..num_partitions { + let k = br.read(rice_k)? as u8; + if k != esc { + decode_partition(br, &mut dst[off..][..psize], k)?; + } else { + let bits = br.read(5)? as u8; + for el in dst[off..].iter_mut().take(psize) { + *el = br.read_s(bits)?; + } + } + off += psize; + } + + Ok(()) +} + +fn apply_fixed_predictor(dst: &mut [i32], order: usize) { + match order { + 1 => { + let mut last = dst[0]; + for el in dst.iter_mut().skip(1) { + *el += last; + last = *el; + } + }, + 2 => { + let mut last0 = dst[1]; + let mut last1 = last0 - dst[0]; + for el in dst.iter_mut().skip(2) { + last1 += *el; + last0 += last1; + *el = last0; + } + }, + 3 => { + let mut last0 = dst[2]; + let mut last1 = last0 - dst[1]; + let mut last2 = last1 - dst[1] + dst[0]; + for el in dst.iter_mut().skip(3) { + last2 += *el; + last1 += last2; + last0 += last1; + *el = last0; + } + }, + 4 => { + let mut last0 = dst[3]; + let mut last1 = last0 - dst[2]; + let mut last2 = last1 - dst[2] + dst[1]; + let mut last3 = last2 - dst[2] + 2 * dst[1] - dst[0]; + for el in dst.iter_mut().skip(4) { + last3 += *el; + last2 += last3; + last1 += last2; + last0 += last1; + *el = last0; + } + }, + _ => unreachable!(), + }; +} + +fn apply_lpc(dst: &mut [i32], filt: &[i32; 16], order: usize, shift: u8) { + for i in order..dst.len() { + let mut sum = 0i64; + for (coef, filt) in dst[i - order..].iter().take(order).zip(filt.iter()) { + sum += i64::from(*coef) * i64::from(*filt); + } + dst[i] += (sum >> shift) as i32; + } +} + +impl FlacDecoder { + fn new() -> Self { + Self { + ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), + chmap: NAChannelMap::new(), + min_blk_size: 0, + max_blk_size: 0, + min_frm_size: 0, + max_frm_size: 0, + channels: 0, + bits: 0, + srate: 0, + residues: [vec![0; MAX_SAMPLES], vec![0; MAX_SAMPLES], + vec![0; MAX_SAMPLES], vec![0; MAX_SAMPLES], + vec![0; MAX_SAMPLES], vec![0; MAX_SAMPLES], + vec![0; MAX_SAMPLES], vec![0; MAX_SAMPLES]], + } + } + fn apply_chmod(&mut self, blocksize: usize, chmod: StereoMode) { + match chmod { + StereoMode::Normal => {}, + StereoMode::LeftSide => { + for i in 0..blocksize { + self.residues[1][i] = self.residues[0][i].wrapping_sub(self.residues[1][i]); + } + }, + StereoMode::SideRight => { + for i in 0..blocksize { + self.residues[0][i] = self.residues[0][i].wrapping_add(self.residues[1][i]); + } + }, + StereoMode::MidSide => { + for i in 0..blocksize { + let r = self.residues[0][i].wrapping_sub(self.residues[1][i] >> 1); + self.residues[0][i] = self.residues[1][i].wrapping_add(r); + self.residues[1][i] = r; + } + }, + }; + } + fn decode_subframe(&mut self, br: &mut BitReader, channel: usize, blocksize: usize, mut samp_bits: u8) -> DecoderResult<()> { + let marker = br.read(1)?; + validate!(marker == 0); + let sftype = br.read(6)?; + + if br.read_bool()? { + let nbits = br.read_code(UintCodeType::UnaryZeroes)?; + validate!(nbits < 32 && samp_bits > nbits as u8); + samp_bits -= nbits as u8; + } + + let dst = &mut self.residues[channel][..blocksize]; + match sftype { + 0x00 => { + let val = br.read_s(samp_bits)?; + for el in dst.iter_mut() { + *el = val; + } + }, + 0x01 => { + for el in dst.iter_mut() { + *el = br.read_s(samp_bits)?; + } + }, + 0x08..=0x0C => { + let order = (sftype - 0x08) as usize; + for el in dst.iter_mut().take(order) { + *el = br.read_s(samp_bits)?; + } + decode_residual(br, &mut dst[order..], order)?; + if order > 0 { + apply_fixed_predictor(dst, order); + } + }, + 0x20..=0x3F => { + let order = (sftype - 0x20) as usize + 1; + for el in dst.iter_mut().take(order) { + *el = br.read_s(samp_bits)?; + } + let precision = br.read(4)? as u8 + 1; + validate!(precision < 16); + let shift = br.read(5)? as u8; + let mut filter = [0i32; 16]; + for el in filter[..order].iter_mut().rev() { + *el = br.read_s(precision)?; + } + decode_residual(br, &mut dst[order..], order)?; + apply_lpc(dst, &filter, order, shift); + }, + _ => return Err(DecoderError::InvalidData), + }; + + Ok(()) + } +} + +impl NADecoder for FlacDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + const DEFAULT_CHANNEL_MAPS: [&str; 8] = [ + "C", + "L,R", + "L,R,C", + "L,R,Ls,Rs", + "L,R,C,Ls,Rs", + "L,R,C,LFE,Ls,Rs", + "L,R,C,LFE,Cs,Ls,Rs", + "L,R,C,LFE,Ls,Rs,Lss,Rss" + ]; + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + if let Some(buf) = info.get_extradata() { + validate!(buf.len() >= 22); + + let mut mr = MemoryReader::new_read(&buf); + let mut br = ByteReader::new(&mut mr); + + self.min_blk_size = br.read_u16be()? as usize; + self.max_blk_size = br.read_u16be()? as usize; + self.min_frm_size = br.read_u24be()? as usize; + self.max_frm_size = br.read_u24be()? as usize; + let tmp = br.read_u64be()?; + self.srate = (tmp >> 44) as u32; + self.channels = (((tmp >> 41) & 7) + 1) as u8; + self.bits = (((tmp >> 36) & 0x1F) + 1) as u8; + //let tot_samples = tmp & ((1 << 36) - 1); + + self.chmap = NAChannelMap::from_str(DEFAULT_CHANNEL_MAPS[(self.channels - 1) as usize]).unwrap(); + let fmt = match self.bits { + 8 | 12 | 16 => SND_S16P_FORMAT, + 24 => SND_S32P_FORMAT, + _ => return Err(DecoderError::NotImplemented), + }; + + self.ainfo = NAAudioInfo::new(self.srate, self.channels as u8, fmt, self.max_blk_size.max(1)); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + if let NACodecTypeInfo::Audio(_) = info.get_properties() { + let pktbuf = pkt.get_buffer(); + validate!(pktbuf.len() >= 9.max(self.min_frm_size)); + + let ref_crc = read_u16be(&pktbuf[pktbuf.len() - 2..]).unwrap_or(0); + let mut crc = 0; + for el in pktbuf.iter().take(pktbuf.len() - 2) { + crc = update_crc16(crc, *el); + } + if crc != ref_crc { + return Err(DecoderError::ChecksumError); + } + + let mut br = BitReader::new(&pktbuf, BitReaderMode::BE); + + let sync = br.read(14)?; + validate!(sync == 0x3FFE); + br.skip(1)?; + let _blocking = br.read(1)?; + let bsize_idx = br.read(4)?; + let srate_idx = br.read(4)?; + let chan_idx = br.read(4)?; + let bits_idx = br.read(3)?; + br.skip(1)?; + // UTF-8 encoded block or sample number + let byte = br.read(8)? as u8; + let len = (!byte).leading_zeros(); + validate!(len <= 5 && len != 1); + if len > 1 { + for _ in 1..len { + let byte = br.read(8)?; + validate!((byte & 0xC0) == 0x80); + } + } + let blocksize = match bsize_idx { + 0 => return Err(DecoderError::InvalidData), + 1 => 192, + 2..=5 => 576 << (bsize_idx - 2), + 6 => br.read(8)? as usize + 1, + 7 => br.read(16)? as usize + 1, + _ => 256 << (bsize_idx - 8), + }; + let srate = match srate_idx { + 0 => self.srate, + 1 => 88200, + 2 => 176400, + 3 => 192000, + 4 => 8000, + 5 => 16000, + 6 => 22050, + 7 => 24000, + 8 => 32000, + 9 => 44100, + 10 => 48000, + 11 => 96000, + 12 => br.read(8)? * 1000, + 13 => br.read(16)?, + 14 => br.read(16)? * 10, + _ => return Err(DecoderError::InvalidData), + }; + validate!(srate != 0 && srate == self.srate); + let (channels, chmod) = match chan_idx { + 0..=7 => (chan_idx as u8 + 1, StereoMode::Normal), + 8 => (2, StereoMode::LeftSide), + 9 => (2, StereoMode::SideRight), + 10 => (2, StereoMode::MidSide), + _ => return Err(DecoderError::InvalidData), + }; + validate!(channels == self.channels); + let bits = match bits_idx { + 0 => self.bits, + 1 => 8, + 2 => 12, + 4 => 16, + 5 => 20, + 6 => 24, + _ => return Err(DecoderError::InvalidData), + }; + validate!(bits == self.bits); + + let end = br.tell() / 8; + let ref_crc = br.read(8)? as u8; + let mut crc = 0; + for el in pktbuf.iter().take(end) { + crc = update_crc8(crc, *el); + } + if crc != ref_crc { + return Err(DecoderError::ChecksumError); + } + + for ch in 0..(channels as usize) { + let samp_bits = match (chmod, ch) { + (StereoMode::LeftSide, 1) | + (StereoMode::SideRight, 0) | + (StereoMode::MidSide, 1) => self.bits + 1, + _ => self.bits, + }; + validate!(samp_bits <= 32); + self.decode_subframe(&mut br, ch, blocksize, samp_bits)?; + } + if channels == 2 { + self.apply_chmod(blocksize, chmod); + } + + let mut abuf = alloc_audio_buffer(self.ainfo, blocksize, self.chmap.clone())?; + let postshift = if self.bits == 24 { 8 } else { 16 - self.bits }; + match abuf { + NABufferType::AudioI16(ref mut adata) => { + let stride = adata.get_stride(); + let dst = adata.get_data_mut().unwrap(); + let mut off = 0; + for residues in self.residues.iter().take(channels as usize) { + let dst = &mut dst[off..][..blocksize]; + for (dst, src) in dst.iter_mut().zip(residues.iter()) { + *dst = (*src << postshift) as i16; + } + off += stride; + } + }, + NABufferType::AudioI32(ref mut adata) => { + let stride = adata.get_stride(); + let dst = adata.get_data_mut().unwrap(); + let mut off = 0; + for residues in self.residues.iter().take(channels as usize) { + let dst = &mut dst[off..][..blocksize]; + for (dst, src) in dst.iter_mut().zip(residues.iter()) { + *dst = *src << postshift; + } + off += stride; + } + }, + _ => unreachable!(), + }; + + let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); + frm.set_duration(Some(blocksize as u64)); + Ok(frm.into_ref()) + } else { + Err(DecoderError::InvalidData) + } + } + fn flush(&mut self) { + } +} + +impl NAOptionHandler for FlacDecoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { + Box::new(FlacDecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::llaudio_register_all_decoders; + use crate::llaudio_register_all_demuxers; + #[test] + fn test_flac() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("flac", "flac", "assets/LLaudio/luckynight.flac", Some(6), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xe689787a, 0x032a98f7, 0xeb6e64f4, 0xfa652132])); + } +} + +fn update_crc8(crc: u8, byte: u8) -> u8 { + CRC8_TABLE[(crc ^ byte) as usize] +} + +fn update_crc16(crc: u16, byte: u8) -> u16 { + (crc << 8) ^ CRC16_TABLE[(((crc >> 8) as u8) ^ byte) as usize] +} + +const CRC8_TABLE: [u8; 256] = [ + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +]; + +const CRC16_TABLE: [u16; 256] = [ + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +]; diff --git a/nihav-llaudio/src/codecs/mod.rs b/nihav-llaudio/src/codecs/mod.rs new file mode 100644 index 0000000..5cc1769 --- /dev/null +++ b/nihav-llaudio/src/codecs/mod.rs @@ -0,0 +1,39 @@ +use nihav_core::codecs::*; + +macro_rules! validate { + ($a:expr) => { if !$a { println!("check failed at {}:{}", file!(), line!()); return Err(DecoderError::InvalidData); } }; +} + +#[cfg(feature="decoder_ape")] +pub mod ape; +#[cfg(feature="decoder_ape")] +mod apepred; +#[cfg(feature="decoder_ape")] +mod apereader; + +#[cfg(feature="decoder_flac")] +pub mod flac; + +#[cfg(feature="decoder_tta")] +pub mod tta; + +#[cfg(feature="decoder_wavpack")] +pub mod wavpack; + +const LL_AUDIO_CODECS: &[DecoderInfo] = &[ +#[cfg(feature="decoder_ape")] + DecoderInfo { name: "ape", get_decoder: ape::get_decoder }, +#[cfg(feature="decoder_flac")] + DecoderInfo { name: "flac", get_decoder: flac::get_decoder }, +#[cfg(feature="decoder_tta")] + DecoderInfo { name: "tta", get_decoder: tta::get_decoder }, +#[cfg(feature="decoder_wavpack")] + DecoderInfo { name: "wavpack", get_decoder: wavpack::get_decoder }, +]; + +/// Registers all available codecs provided by this crate. +pub fn llaudio_register_all_decoders(rd: &mut RegisteredDecoders) { + for decoder in LL_AUDIO_CODECS.iter() { + rd.add_decoder(decoder.clone()); + } +} diff --git a/nihav-llaudio/src/codecs/tta.rs b/nihav-llaudio/src/codecs/tta.rs new file mode 100644 index 0000000..03eb515 --- /dev/null +++ b/nihav-llaudio/src/codecs/tta.rs @@ -0,0 +1,415 @@ +use nihav_core::codecs::*; +use nihav_core::io::byteio::*; +use nihav_core::io::bitreader::*; +use nihav_core::io::intcode::*; + +#[derive(Default)] +struct Filter { + predictor: i32, + error: i32, + round: i32, + shift: u8, + qm: [i32; 8], + dx: [i32; 8], + dl: [i32; 8], +} + +impl Filter { + fn reset(&mut self, bpp: u8) { + const SHIFTS: [u8; 3] = [10, 9, 10]; + self.shift = SHIFTS[(bpp - 1) as usize]; + self.round = (1 << self.shift) >> 1; + self.error = 0; + self.qm = [0; 8]; + self.dx = [0; 8]; + self.dl = [0; 8]; + self.predictor = 0; + } + fn hybrid_filt(&mut self, delta: i32) -> i32 { + if self.error < 0 { + for (qm, dx) in self.qm.iter_mut().zip(self.dx.iter()) { + *qm -= *dx; + } + } else if self.error > 0 { + for (qm, dx) in self.qm.iter_mut().zip(self.dx.iter()) { + *qm += *dx; + } + } + + let mut sum = self.round; + for (dl, qm) in self.dl.iter().zip(self.qm.iter()) { + sum = sum.wrapping_add(*dl * *qm); + } + self.error = delta; + let val = (sum >> self.shift) + delta; + + for i in 0..4 { + self.dx[i] = self.dx[i + 1]; + self.dl[i] = self.dl[i + 1]; + } + self.dx[4] = (self.dl[4] >> 30) | 1; + self.dx[5] = ((self.dl[5] >> 30) | 2) & !1; + self.dx[6] = ((self.dl[6] >> 30) | 2) & !1; + self.dx[7] = ((self.dl[7] >> 30) | 4) & !3; + self.dl[4] = -self.dl[5]; + self.dl[5] = -self.dl[6]; + self.dl[6] = val - self.dl[7]; + self.dl[7] = val; + self.dl[5] += self.dl[6]; + self.dl[4] += self.dl[5]; + + val + } + fn static_pred(&mut self, bpp: u8, mut val: i32) -> i32 { + val += match bpp { + 0 => ((i64::from(self.predictor) * 15) >> 4) as i32, + 1 | 2 => ((i64::from(self.predictor) * 31) >> 5) as i32, + _ => self.predictor, + }; + self.predictor = val; + val + } +} + +struct RiceDecoder { + k: u8, + sum: u32, +} + +impl RiceDecoder { + fn new() -> Self { + let k = 10; + Self { + k, sum: RiceDecoder::limit(k) + } + } + fn reset(&mut self) { + self.k = 10; + self.sum = RiceDecoder::limit(self.k); + } + fn limit(k: u8) -> u32 { 1 << (k + 4).min(31) } + fn update(&mut self, val: u32) { + self.sum -= self.sum >> 4; + self.sum += val; + if self.k > 0 && self.sum < Self::limit(self.k) { + self.k -= 1; + } else if self.sum > Self::limit(self.k + 1) { + self.k += 1; + } + } +} + +trait Output { + fn set(&mut self, val: i32); +} + +impl Output for i16 { + fn set(&mut self, val: i32) { *self = val as i16; } +} +impl Output for i32 { + fn set(&mut self, val: i32) { *self = val; } +} + +struct ChannelDecoder { + filt: Filter, + rice0: RiceDecoder, + rice1: RiceDecoder, + offset: usize, + sample: i32, +} + +impl ChannelDecoder { + fn new() -> Self { + Self { + filt: Filter::default(), + rice0: RiceDecoder::new(), + rice1: RiceDecoder::new(), + offset: 0, + sample: 0, + } + } +} + +struct TTADecoder { + ainfo: NAAudioInfo, + chmap: NAChannelMap, + bpp: u8, + framelen: u32, + nsamples: u32, + ch_dec: Vec, +} + +impl TTADecoder { + fn new() -> Self { + Self { + ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), + chmap: NAChannelMap::new(), + bpp: 0, + framelen: 0, + nsamples: 0, + ch_dec: Vec::new(), + } + } + fn decode_frame(&mut self, br: &mut BitReader, dst: &mut [T], stride: usize) -> DecoderResult { + for (i, chdec) in self.ch_dec.iter_mut().enumerate() { + chdec.offset = i * stride; + chdec.rice0.reset(); + chdec.rice1.reset(); + chdec.filt.reset(self.bpp); + } + + let channels = self.ch_dec.len(); + let tail_len = self.nsamples % self.framelen; + + for sample in 0..self.framelen { + for chdec in self.ch_dec.iter_mut() { + let pfx = br.read_code(UintCodeType::UnaryOnes)?; + let (k, pfx, level1) = if pfx == 0 { + (chdec.rice0.k, 0, false) + } else { + (chdec.rice1.k, pfx - 1, true) + }; + let mut val = (pfx << k) | br.read(k)?; + if level1 { + chdec.rice1.update(val); + val += 1 << chdec.rice0.k; + } + chdec.rice0.update(val); + let delta = if (val & 1) == 0 { + -((val >> 1) as i32) + } else { + ((val + 1) >> 1) as i32 + }; + let hval = chdec.filt.hybrid_filt(delta); + chdec.sample = chdec.filt.static_pred(self.bpp, hval); + } + if channels > 1 { + self.ch_dec[channels - 1].sample += self.ch_dec[channels - 2].sample / 2; + let mut last = self.ch_dec[channels - 1].sample; + for chdec in self.ch_dec.iter_mut().rev().skip(1) { + chdec.sample = last - chdec.sample; + last = chdec.sample; + } + } + for chdec in self.ch_dec.iter_mut() { + dst[chdec.offset].set(chdec.sample); + chdec.offset += 1; + } + if (tail_len > 0) && (sample == tail_len - 1) && (br.left() < 40) { + return Ok(false); + } + } + + Ok(true) + } +} + +fn check_crc(buf: &[u8]) -> bool { + if buf.len() <= 4 { + return false; + } + let mut crc = 0xFFFFFFFF; + let ref_crc = read_u32le(&buf[buf.len() - 4..]).unwrap_or(0); + for el in buf.iter().take(buf.len() - 4) { + crc = CRC32_TAB[(crc as u8 ^ *el) as usize] ^ (crc >> 8); + } + crc == !ref_crc +} + +impl NADecoder for TTADecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + if let Some(buf) = info.get_extradata() { + if !check_crc(&buf) { + return Err(DecoderError::ChecksumError); + } + let mut mr = MemoryReader::new_read(&buf); + let mut br = ByteReader::new(&mut mr); + let tag = br.read_tag()?; + validate!(&tag == b"TTA1"); + let afmt = br.read_u16le()?; + if afmt != 1 { + return Err(DecoderError::NotImplemented); + } + let channels = br.read_u16le()?; + validate!(channels > 0 && channels < 256); + let bpp = br.read_u16le()?; + validate!(bpp > 0 && bpp <= 32); + let srate = br.read_u32le()?; + validate!(srate > 256 && srate < 1048576); + self.nsamples = br.read_u32le()?; + validate!(self.nsamples > 0); + + self.framelen = srate * 256 / 245; + + self.chmap = if channels == 1 { + NAChannelMap::from_str("C").unwrap() + } else if channels == 2 { + NAChannelMap::from_str("L,R").unwrap() + } else { + return Err(DecoderError::NotImplemented); + }; + let fmt = match bpp { + 8 | 16 => SND_S16P_FORMAT, + 24 | 32 => SND_S32P_FORMAT, + _ => return Err(DecoderError::NotImplemented), + }; + self.bpp = (bpp / 8) as u8; + self.ch_dec = Vec::with_capacity(channels as usize); + for _ in 0..channels { + self.ch_dec.push(ChannelDecoder::new()); + } + + self.ainfo = NAAudioInfo::new(srate, channels as u8, fmt, self.framelen as usize); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + if let NACodecTypeInfo::Audio(_) = info.get_properties() { + let pktbuf = pkt.get_buffer(); + validate!(pktbuf.len() > 4); + if !check_crc(&pktbuf) { + return Err(DecoderError::ChecksumError); + } + + let mut br = BitReader::new(&pktbuf, BitReaderMode::LE); + + let mut abuf = alloc_audio_buffer(self.ainfo, self.framelen as usize, self.chmap.clone())?; + let duration = match abuf { + NABufferType::AudioI16(ref mut adata) => { + let stride = adata.get_stride(); + let dst = adata.get_data_mut().unwrap(); + let not_last = self.decode_frame(&mut br, dst, stride)?; + if not_last { + self.framelen + } else { + adata.truncate((self.nsamples % self.framelen) as usize); + self.nsamples % self.framelen + } + }, + NABufferType::AudioI32(ref mut adata) => { + let stride = adata.get_stride(); + let dst = adata.get_data_mut().unwrap(); + let not_last = self.decode_frame(&mut br, dst, stride)?; + if not_last { + self.framelen + } else { + adata.truncate((self.nsamples % self.framelen) as usize); + self.nsamples % self.framelen + } + }, + _ => unreachable!(), + }; + + let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); + frm.set_duration(Some(u64::from(duration))); + Ok(frm.into_ref()) + } else { + Err(DecoderError::InvalidData) + } + } + fn flush(&mut self) { + } +} + +impl NAOptionHandler for TTADecoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { + Box::new(TTADecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::llaudio_register_all_decoders; + use crate::llaudio_register_all_demuxers; + #[test] + fn test_tta() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("tta", "tta", "assets/LLaudio/luckynight.tta", Some(3), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xce0fe9c4, 0xa69eefda, 0xe182008c, 0xe941db3f])); + } +} + +const CRC32_TAB: [u32; 256] = [ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +]; diff --git a/nihav-llaudio/src/codecs/wavpack.rs b/nihav-llaudio/src/codecs/wavpack.rs new file mode 100644 index 0000000..07aef40 --- /dev/null +++ b/nihav-llaudio/src/codecs/wavpack.rs @@ -0,0 +1,1195 @@ +use nihav_core::codecs::*; +use nihav_core::io::byteio::*; +use nihav_core::io::bitreader::*; +use nihav_core::io::intcode::*; + +const SAMPLE_RATES: [u32; 15] = [ + 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000, 192000 +]; +const WV_FLAG_MONO: u32 = 1 << 2; +const WV_FLAG_HYBRID: u32 = 1 << 3; +const WV_FLAG_JSTEREO: u32 = 1 << 4; +//const WV_FLAG_CH_DECORR: u32 = 1 << 5; +//const WV_FLAG_HYB_NOISE_SHAPING: u32 = 1 << 6; +const WV_FLAG_FLOATS: u32 = 1 << 7; +const WV_FLAG_EXT_INTEGERS: u32 = 1 << 8; +const WV_FLAG_HYB_BITRATE: u32 = 1 << 9; +//const WV_FLAG_HYB_BALANCED_NOISE: u32 = 1 << 10; +const WV_FLAG_START_BLOCK: u32 = 1 << 11; +const WV_FLAG_END_BLOCK: u32 = 1 << 12; +//const WV_FLAG_HAS_CRC: u32 = 1 << 28; +const WV_FLAG_FALSE_STEREO: u32 = 1 << 30; +const WV_FLAG_DSD_AUDIO: u32 = 1 << 31; + +const WV_STREAM_FLAGS: u32 = 0x8000018B; + +#[derive(Clone,Copy,Default)] +struct WVHeader { + size: usize, + ver: u16, + tot_samples: u64, + block_index: u64, + block_samples: u32, + flags: u32, + crc: u32, +} + +const WV_HEADER_SIZE: usize = 32; + +impl WVHeader { + fn parse(src: &[u8]) -> DecoderResult { + let mut mr = MemoryReader::new_read(src); + let mut br = ByteReader::new(&mut mr); + let tag = br.read_tag()?; + validate!(&tag == b"wvpk"); + let mut hdr = Self::default(); + hdr.size = br.read_u32le()? as usize; + validate!(hdr.size >= 24); + hdr.ver = br.read_u16le()?; + validate!(hdr.ver >= 0x402 || hdr.ver <= 0x410); + let top_idx = br.read_byte()?; + let top_samps = br.read_byte()?; + hdr.tot_samples = u64::from(br.read_u32le()?) | (u64::from(top_samps) << 32); + hdr.block_index = u64::from(br.read_u32le()?) | (u64::from(top_idx) << 32); + hdr.block_samples = br.read_u32le()?; + hdr.flags = br.read_u32le()?; + hdr.crc = br.read_u32le()?; + Ok(hdr) + } + fn stream_eq(&self, rval: &Self) -> bool { + self.ver == rval.ver && + (self.flags & WV_STREAM_FLAGS) == (rval.flags & WV_STREAM_FLAGS) + } + fn block_eq(&self, rval: &Self) -> bool { + self.stream_eq(rval) && self.block_index == rval.block_index && + self.tot_samples == rval.tot_samples && + self.block_samples == rval.block_samples + } + fn is_start_block(&self) -> bool { + (self.flags & WV_FLAG_START_BLOCK) != 0 + } + fn is_end_block(&self) -> bool { + (self.flags & WV_FLAG_END_BLOCK) != 0 + } + fn get_num_channels(&self) -> u8 { + if (self.flags & WV_FLAG_MONO) != 0 && (self.flags & WV_FLAG_FALSE_STEREO) == 0 { 1 } else { 2 } + } + fn get_sample_rate(&self) -> u32 { + let idx = ((self.flags >> 23) & 0xF) as usize; + if idx != 15 { + SAMPLE_RATES[idx] + } else { + 0 + } + } + fn get_size(&self) -> usize { + self.size - (WV_HEADER_SIZE - 8) + } + fn get_bits(&self) -> u8 { + (((self.flags & 3) + 1) * 8) as u8 + } +} + +fn wv_log2lin(val: i32) -> i32 { + let sign = val < 0; + let aval = val.abs(); + let mant = 0x100 | i32::from(WV_EXP_TABLE[(aval & 0xFF) as usize]); + let exp = aval >> 8; + let aval = if exp >= 9 { + mant << (exp - 9) + } else { + mant >> (9 - exp) + }; + if !sign { + aval + } else { + -aval + } +} + +fn wv_lin2log(val: u32) -> u32 { + if val == 0 { + 0 + } else if val == 1 { + 0x100 + } else { + let val = val + (val >> 9); + let bits = 32 - val.leading_zeros(); + if bits < 9 { + (bits << 8) + u32::from(WV_LOG_TABLE[((val << (9 - bits)) & 0xFF) as usize]) + } else { + (bits << 8) + u32::from(WV_LOG_TABLE[((val >> (bits - 9)) & 0xFF) as usize]) + } + } +} + +#[derive(Clone,Copy,Default)] +struct Decorrelator { + delta: i32, + value: i32, + weight_a: i32, + weight_b: i32, + samples_a: [i32; 8], + samples_b: [i32; 8], +} + +impl Decorrelator { + fn decorrelate_mono(&mut self, l: i32, pos: usize) -> i32 { + let mode = self.value; + let (a, npos) = if mode > 8 { + let a = if (mode & 1) != 0 { + 2 * self.samples_a[0] - self.samples_a[1] + } else { + (3 * self.samples_a[0] - self.samples_a[1]) >> 1 + }; + self.samples_a[1] = self.samples_a[0]; + (a, 0) + } else { + (self.samples_a[pos], (pos + mode as usize) & 7) + }; + let l2 = l + ((i64::from(self.weight_a) * i64::from(a) + 512) >> 10) as i32; + if (a != 0) && (l != 0) { + self.weight_a -= ((((l ^ a) >> 30) & 2) - 1) * self.delta; + } + self.samples_a[npos] = l2; + l2 + } + fn decorrelate_stereo(&mut self, l: i32, r: i32, pos: usize) -> (i32, i32) { + let mode = self.value; + if mode > 0 { + let (a, b, npos) = if mode > 8 { + let (a, b) = if (mode & 1) != 0 { + (2 * self.samples_a[0] - self.samples_a[1], + 2 * self.samples_b[0] - self.samples_b[1]) + } else { + ((3 * self.samples_a[0] - self.samples_a[1]) >> 1, + (3 * self.samples_b[0] - self.samples_b[1]) >> 1) + }; + self.samples_a[1] = self.samples_a[0]; + self.samples_b[1] = self.samples_b[0]; + (a, b, 0) + } else { + (self.samples_a[pos], self.samples_b[pos], (pos + mode as usize) & 7) + }; + let l2 = l + ((i64::from(self.weight_a) * i64::from(a) + 512) >> 10) as i32; + let r2 = r + ((i64::from(self.weight_b) * i64::from(b) + 512) >> 10) as i32; + if (a != 0) && (l != 0) { + self.weight_a -= ((((l ^ a) >> 30) & 2) - 1) * self.delta; + } + if (b != 0) && (r != 0) { + self.weight_b -= ((((r ^ b) >> 30) & 2) - 1) * self.delta; + } + self.samples_a[npos] = l2; + self.samples_b[npos] = r2; + (l2, r2) + } else if mode == -1 { + let l2 = l + ((i64::from(self.weight_a) * i64::from(self.samples_a[0]) + 512) >> 10) as i32; + let r2 = r + ((i64::from(self.weight_b) * i64::from(l2) + 512) >> 10) as i32; + self.update_weight_a(self.samples_a[0], l); + self.update_weight_b(l2, r); + self.samples_a[0] = r2; + (l2, r2) + } else { + let r2 = r + ((i64::from(self.weight_b) * i64::from(self.samples_b[0]) + 512) >> 10) as i32; + self.update_weight_b(self.samples_b[0], r); + let rr = if mode == -3 { + let nr = self.samples_a[0]; + self.samples_a[0] = r2; + nr + } else { + r2 + }; + let l2 = l + ((i64::from(self.weight_a) * i64::from(rr) + 512) >> 10) as i32; + self.update_weight_a(rr, l); + self.samples_b[0] = l2; + (l2, r2) + } + } + fn update_weight_a(&mut self, l: i32, r: i32) { + if (l != 0) && (r != 0) { + if (l ^ r) < 0 { + self.weight_a = (self.weight_a - self.delta).max(-1024) + } else { + self.weight_a = (self.weight_a + self.delta).min(1024) + } + } + } + fn update_weight_b(&mut self, l: i32, r: i32) { + if (l != 0) && (r != 0) { + if (l ^ r) < 0 { + self.weight_b = (self.weight_b - self.delta).max(-1024) + } else { + self.weight_b = (self.weight_b + self.delta).min(1024) + } + } + } +} + +#[derive(Default)] +struct DecState { + median: [[u32; 3]; 2], + zero: bool, + one: bool, + num_zeroes: u32, + ebits: u8, + shift: u8, + and: i32, + or: i32, + post_shift: u8, + slow_level: [u32; 2], + br_acc: [u32; 2], + br_delta: [u32; 2], + hyb_max: i32, + hyb_min: i32, + has_hbr: bool, + stereo: bool, + error_lim: [u32; 2], +} + +fn read_biased_code(br: &mut BitReader) -> DecoderResult { + let val = br.read_code(UintCodeType::UnaryOnes)?; + validate!(val < 25); + if val < 2 { + Ok(val) + } else { + let bits = val - 1; + Ok((1 << bits) | br.read(bits as u8)?) + } +} +fn read_tail(br: &mut BitReader, bits: u32) -> DecoderResult { + if bits < 1 { + Ok(0) + } else { + let p = 31 - bits.leading_zeros(); + let esc = (1 << (p + 1)) - (bits + 1); + let val = br.read(p as u8)?; + if val < esc { + Ok(val) + } else { + Ok(val * 2 - esc + br.read(1)?) + } + } +} + +impl DecState { + fn read_sample(&mut self, br: &mut BitReader, channel: usize) -> DecoderResult { + if (self.median[0][0] < 2) && (self.median[1][0] < 2) && !self.zero && !self.one { + if self.num_zeroes > 0 { + self.num_zeroes -= 1; + if self.num_zeroes != 0 { + return Ok(0); + } + } else { + self.num_zeroes = read_biased_code(br)?; + if self.num_zeroes != 0 { + self.median = [[0; 3]; 2]; + return Ok(0); + } + } + } + let val = if self.zero { + self.zero = false; + 0 + } else { + let mut val = br.read_code(UintCodeType::UnaryOnes)?; + validate!(val <= 16); + if val == 16 { + val += read_biased_code(br)?; + } + let one = (val & 1) != 0; + val >>= 1; + if self.one { + val += 1; + } + self.one = one; + self.zero = !one; + val + }; + + let (base, add) = match val { + 0 => { + let add = self.get_median(channel, 0) - 1; + self.dec_median(channel, 0); + (0, add) + }, + 1 => { + let base = self.get_median(channel, 0); + let add = self.get_median(channel, 1) - 1; + self.inc_median(channel, 0); + self.dec_median(channel, 1); + (base, add) + }, + 2 => { + let base = self.get_median(channel, 0) + self.get_median(channel, 1); + let add = self.get_median(channel, 2) - 1; + self.inc_median(channel, 0); + self.inc_median(channel, 1); + self.dec_median(channel, 2); + (base, add) + }, + _ => { + let base = self.get_median(channel, 0) + self.get_median(channel, 1) + self.get_median(channel, 2) * (val - 2); + let add = self.get_median(channel, 2) - 1; + self.inc_median(channel, 0); + self.inc_median(channel, 1); + self.inc_median(channel, 2); + (base, add) + }, + }; + let val = base + read_tail(br, add)?; + + if !br.read_bool()? { + Ok(val as i32) + } else { + Ok(!val as i32) + } + } + fn read_sample_hyb(&mut self, br: &mut BitReader, channel: usize) -> DecoderResult { + if (self.median[0][0] < 2) && (self.median[1][0] < 2) && !self.zero && !self.one { + if self.num_zeroes > 0 { + self.num_zeroes -= 1; + if self.num_zeroes != 0 { + self.decay_slev(channel); + return Ok(0); + } + } else { + self.num_zeroes = read_biased_code(br)?; + if self.num_zeroes != 0 { + self.median = [[0; 3]; 2]; + self.decay_slev(channel); + return Ok(0); + } + } + } + let val = if self.zero { + self.zero = false; + 0 + } else { + let mut val = br.read_code(UintCodeType::UnaryOnes)?; + validate!(val <= 16); + if val == 16 { + val += read_biased_code(br)?; + } + let one = (val & 1) != 0; + val >>= 1; + if self.one { + val += 1; + } + self.one = one; + self.zero = !one; + val + }; + + if channel == 0 { + self.update_error_limit(); + } + + let (mut base, mut add) = match val { + 0 => { + let add = self.get_median(channel, 0) - 1; + self.dec_median(channel, 0); + (0, add) + }, + 1 => { + let base = self.get_median(channel, 0); + let add = self.get_median(channel, 1) - 1; + self.inc_median(channel, 0); + self.dec_median(channel, 1); + (base, add) + }, + 2 => { + let base = self.get_median(channel, 0) + self.get_median(channel, 1); + let add = self.get_median(channel, 2) - 1; + self.inc_median(channel, 0); + self.inc_median(channel, 1); + self.dec_median(channel, 2); + (base, add) + }, + _ => { + let base = self.get_median(channel, 0) + self.get_median(channel, 1) + self.get_median(channel, 2) * (val - 2); + let add = self.get_median(channel, 2) - 1; + self.inc_median(channel, 0); + self.inc_median(channel, 1); + self.inc_median(channel, 2); + (base, add) + }, + }; + let val = if self.error_lim[channel] == 0 { + base + read_tail(br, add)? + } else { + let mut mid = (base * 2 + add + 1) >> 1; + while add > self.error_lim[channel] { + if br.read_bool()? { + add += base; + add -= mid; + base = mid; + } else { + add = mid - base - 1; + } + mid = (base * 2 + add + 1) >> 1; + } + mid + }; + + if self.has_hbr { + self.decay_slev(channel); + self.slow_level[channel] += wv_lin2log(val); + } + + if !br.read_bool()? { + Ok(val as i32) + } else { + Ok(!val as i32) + } + } + fn decay_slev(&mut self, channel: usize) { + self.slow_level[channel] -= (self.slow_level[channel] + 0x80) >> 8; + } + fn update_error_limit(&mut self) { + let mut br = [0; 2]; + let mut sl = [0; 2]; + + for i in 0..2 { + self.br_acc[i] += self.br_delta[i]; + br[i] = self.br_acc[i] >> 16; + sl[i] = (self.slow_level[i] + 0x80) >> 8; + } + + if self.stereo && self.has_hbr { + let balance = ((sl[1] as i32) - (sl[0] as i32) + (br[1] as i32) + 1) >> 1; + if balance > (br[0] as i32) { + br[1] = br[0] << 1; + br[0] = 0; + } else if -balance > (br[0] as i32) { + br[0] <<= 1; + br[1] = 0; + } else { + br[1] = ((br[0] as i32) + balance) as u32; + br[0] = ((br[0] as i32) - balance) as u32; + } + } + for i in 0..2 { + self.error_lim[i] = if self.has_hbr { + if sl[i] + 0x100 > br[i] { + wv_log2lin((sl[i] + 0x100 - br[i]) as i32) as u32 + } else { + 0 + } + } else { + wv_log2lin(br[i] as i32) as u32 + }; + } + } + fn get_median(&self, channel: usize, idx: usize) -> u32 { + (self.median[channel][idx] >> 4) + 1 + } + fn inc_median(&mut self, channel: usize, idx: usize) { + self.median[channel][idx] += ((self.median[channel][idx] + (128 >> idx)) / (128 >> idx)) * 5; + } + fn dec_median(&mut self, channel: usize, idx: usize) { + self.median[channel][idx] -= ((self.median[channel][idx] + (128 >> idx) - 2) / (128 >> idx)) * 2; + } + fn produce_sample_common(&self, ebr: &mut BitReader, mut samp: i32) -> i32 { + if self.ebits > 0 { + samp <<= self.ebits; + if ebr.left() >= self.ebits as isize { + samp |= ebr.read(self.ebits).unwrap_or(0) as i32; + } + } + let bit = (samp & self.and) | self.or; + ((samp + bit) << self.shift) - bit + } + fn produce_sample(&self, ebr: &mut BitReader, samp: i32) -> i32 { + self.produce_sample_common(ebr, samp) << self.post_shift + } + fn produce_sample_hyb(&self, ebr: &mut BitReader, samp: i32) -> i32 { + self.produce_sample_common(ebr, samp).max(self.hyb_min).min(self.hyb_max) << self.post_shift + } +} + +struct DecorrState { + decorr: [Decorrelator; 16], + num_decorr: usize, +} + +impl DecorrState { + fn new() -> Self { + Self { + decorr: [Decorrelator::default(); 16], + num_decorr: 0, + } + } + fn reset(&mut self) { + self.decorr = [Decorrelator::default(); 16]; + self.num_decorr = 0; + } +} + +struct WavPackDecoder { + ainfo: NAAudioInfo, + chmap: NAChannelMap, + header: WVHeader, + + dstate: DecorrState, +} + +fn get_subblock(br: &mut ByteReader) -> DecoderResult<(u8, usize)> { + let id1 = br.read_byte()?; + let id = id1 & 0x3F; + let mut len = 2 * if (id1 & 0x80) == 0 { + br.read_byte()? as usize + } else { + br.read_u24le()? as usize + }; + if (id1 & 0x40) != 0 { + validate!(len > 0); + len -= 1; + } + Ok((id, len)) +} + +trait Output { + fn set(&mut self, val: i32); +} + +impl Output for i16 { + fn set(&mut self, val: i32) { *self = val as i16; } +} +impl Output for i32 { + fn set(&mut self, val: i32) { *self = val; } +} + +fn unpack_mono(br: &mut BitReader, ebr: &mut BitReader, state: &mut DecState, decorr: &mut DecorrState, dst: &mut [T], len: usize) -> DecoderResult { + let mut crc = 0xFFFFFFFFu32; + + for (i, dst) in dst[..len].iter_mut().enumerate() { + let mut l = state.read_sample(br, 0)?; + for decorr in decorr.decorr[..decorr.num_decorr].iter_mut() { + l = decorr.decorrelate_mono(l, i & 7); + } + crc = crc.wrapping_mul(3).wrapping_add(l as u32); + l = state.produce_sample(ebr, l); + dst.set(l); + } + + Ok(crc) +} + +#[allow(clippy::too_many_arguments)] +fn unpack_stereo(br: &mut BitReader, ebr: &mut BitReader, state: &mut DecState, decorr: &mut DecorrState, dst: &mut [T], off0: usize, off1: usize, len: usize, is_joint: bool) -> DecoderResult { + let mut crc = 0xFFFFFFFFu32; + + for i in 0..len { + let mut l = state.read_sample(br, 0)?; + let mut r = state.read_sample(br, 1)?; + for decorr in decorr.decorr[..decorr.num_decorr].iter_mut() { + let (pl, pr) = decorr.decorrelate_stereo(l, r, i & 7); + l = pl; + r = pr; + } + if is_joint { + r -= l >> 1; + l += r; + } + crc = crc.wrapping_mul(3).wrapping_add(l as u32).wrapping_mul(3).wrapping_add(r as u32); + l = state.produce_sample(ebr, l); + r = state.produce_sample(ebr, r); + dst[off0 + i].set(l); + dst[off1 + i].set(r); + } + + Ok(crc) +} + +fn unpack_mono_hyb(br: &mut BitReader, ebr: &mut BitReader, state: &mut DecState, decorr: &mut DecorrState, dst: &mut [T], len: usize) -> DecoderResult { + let mut crc = 0xFFFFFFFFu32; + + for (i, dst) in dst[..len].iter_mut().enumerate() { + let mut l = state.read_sample_hyb(br, 0)?; + for decorr in decorr.decorr[..decorr.num_decorr].iter_mut() { + l = decorr.decorrelate_mono(l, i & 7); + } + crc = crc.wrapping_mul(3).wrapping_add(l as u32); + l = state.produce_sample_hyb(ebr, l); + dst.set(l); + } + + Ok(crc) +} + +#[allow(clippy::too_many_arguments)] +fn unpack_stereo_hyb(br: &mut BitReader, ebr: &mut BitReader, state: &mut DecState, decorr: &mut DecorrState, dst: &mut [T], off0: usize, off1: usize, len: usize, is_joint: bool) -> DecoderResult { + let mut crc = 0xFFFFFFFFu32; + + for i in 0..len { + let mut l = state.read_sample_hyb(br, 0)?; + let mut r = state.read_sample_hyb(br, 1)?; + for decorr in decorr.decorr[..decorr.num_decorr].iter_mut() { + let (pl, pr) = decorr.decorrelate_stereo(l, r, i & 7); + l = pl; + r = pr; + } + if is_joint { + r -= l >> 1; + l += r; + } + crc = crc.wrapping_mul(3).wrapping_add(l as u32).wrapping_mul(3).wrapping_add(r as u32); + l = state.produce_sample_hyb(ebr, l); + r = state.produce_sample_hyb(ebr, r); + dst[off0 + i].set(l); + dst[off1 + i].set(r); + } + + Ok(crc) +} + +impl WavPackDecoder { + fn new() -> Self { + Self { + ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), + chmap: NAChannelMap::new(), + header: WVHeader::default(), + + dstate: DecorrState::new(), + } + } + #[allow(clippy::cyclomatic_complexity)] + fn decode_block(&mut self, hdr: &WVHeader, src: &[u8], start_ch: usize, abuf: &mut NABufferType) -> DecoderResult<()> { + let mut mr = MemoryReader::new_read(src); + let mut br = ByteReader::new(&mut mr); + let mut has_terms = false; + let mut has_weights = false; + let mut has_samples = false; + let mut has_hybrid = false; + let is_mono = (hdr.flags & (WV_FLAG_MONO | WV_FLAG_FALSE_STEREO)) != 0; + let cur_channels = if is_mono { 1 } else { 2 }; + let mut data_pos = 0; + let mut data_len = 0; + let mut ebits_pos = 0; + let mut ebits_len = 0; + let mut dec_state = DecState::default(); + self.dstate.reset(); + dec_state.post_shift = if (hdr.get_bits() & 8) != 0 { 8 } else { 0 }; + dec_state.post_shift += ((hdr.flags >> 13) & 0x1F) as u8; + validate!(dec_state.post_shift < 32); + dec_state.hyb_max = 0x7FFFFFFF >> (32 - hdr.get_bits()); + dec_state.hyb_min = -dec_state.hyb_max - 1; + let is_hybrid = (hdr.flags & WV_FLAG_HYBRID) != 0; + let has_hybrid_br = (hdr.flags & WV_FLAG_HYB_BITRATE) != 0; + dec_state.has_hbr = has_hybrid_br; + dec_state.stereo = !is_mono; + while br.left() > 0 { + let (id, len) = get_subblock(&mut br)?; + match id { + 0x02 => { //decorr terms + self.dstate.num_decorr = len; + validate!(self.dstate.num_decorr <= self.dstate.decorr.len()); + for decorr in self.dstate.decorr[..self.dstate.num_decorr].iter_mut().rev() { + let val = br.read_byte()?; + decorr.value = i32::from(val & 0x1F) - 5; + decorr.delta = i32::from(val >> 5); + } + has_terms = true; + }, + 0x03 => { //decorr weights + validate!(has_terms); + validate!(len <= self.dstate.num_decorr * cur_channels); + for decorr in self.dstate.decorr[..self.dstate.num_decorr].iter_mut().rev().take(len / cur_channels) { + let val = br.read_byte()? as i8; + decorr.weight_a = i32::from(val) << 3; + if decorr.weight_a > 0 { + decorr.weight_a += (decorr.weight_a + 64) >> 7; + } + if !is_mono { + let val = br.read_byte()? as i8; + decorr.weight_b = i32::from(val) << 3; + if decorr.weight_b > 0 { + decorr.weight_b += (decorr.weight_b + 64) >> 7; + } + } + } + has_weights = true; + }, + 0x04 => { //decorr samples + validate!(has_weights); + let end = br.tell() + (len as u64); + for decorr in self.dstate.decorr[..self.dstate.num_decorr].iter_mut().rev() { + if br.tell() == end { + break; + } + if decorr.value > 8 { + let a0 = br.read_u16le()? as i16; + let a1 = br.read_u16le()? as i16; + decorr.samples_a[0] = wv_log2lin(i32::from(a0)); + decorr.samples_a[1] = wv_log2lin(i32::from(a1)); + if !is_mono { + let b0 = br.read_u16le()? as i16; + let b1 = br.read_u16le()? as i16; + decorr.samples_b[0] = wv_log2lin(i32::from(b0)); + decorr.samples_b[1] = wv_log2lin(i32::from(b1)); + } + } else if decorr.value < 0 { + let a0 = br.read_u16le()? as i16; + let b0 = br.read_u16le()? as i16; + decorr.samples_a[0] = wv_log2lin(i32::from(a0)); + decorr.samples_b[0] = wv_log2lin(i32::from(b0)); + } else { + let len = decorr.value as usize; + for i in 0..len { + let a = br.read_u16le()? as i16; + decorr.samples_a[i] = wv_log2lin(i32::from(a)); + if !is_mono { + let b = br.read_u16le()? as i16; + decorr.samples_b[i] = wv_log2lin(i32::from(b)); + } + } + } + } + has_samples = true; + }, + 0x05 => { //entropy vars + validate!(len == 6 * cur_channels); + for el in dec_state.median[0].iter_mut() { + *el = wv_log2lin(i32::from(br.read_u16le()? as i16)) as u32; + } + if !is_mono { + for el in dec_state.median[1].iter_mut() { + *el = wv_log2lin(i32::from(br.read_u16le()? as i16)) as u32; + } + } + }, + 0x06 => { //hybrid parameters + validate!(is_hybrid); + let end = br.tell() + (len as u64); + if has_hybrid_br { + for el in dec_state.slow_level.iter_mut().take(cur_channels) { + *el = wv_log2lin(i32::from(br.read_u16le()? as i16)) as u32; + } + } + for el in dec_state.br_acc.iter_mut().take(cur_channels) { + *el = u32::from(br.read_u16le()?) << 16; + } + if br.tell() < end { + for el in dec_state.br_delta.iter_mut().take(cur_channels) { + *el = wv_log2lin(i32::from(br.read_u16le()? as i16)) as u32; + } + } + validate!(br.tell() == end); + has_hybrid = true; + }, + 0x08 => { + validate!((hdr.flags & WV_FLAG_FLOATS) != 0); + return Err(DecoderError::NotImplemented); + }, + 0x09 => { + validate!((hdr.flags & WV_FLAG_EXT_INTEGERS) != 0); + validate!(len == 4); + let ebits = br.read_byte()?; + let mode1 = br.read_byte()?; + let mode2 = br.read_byte()?; + let mode3 = br.read_byte()?; + if ebits != 0 { + dec_state.ebits = ebits; + } else if mode1 != 0 { + dec_state.shift = mode1; + } else if mode2 != 0 { + dec_state.and = 1; + dec_state.or = 1; + dec_state.shift = mode2; + } else if mode3 != 0 { + dec_state.and = 1; + dec_state.shift = mode3; + } + if is_hybrid && hdr.get_bits() == 32 && dec_state.post_shift < 8 && dec_state.shift > 8 { + dec_state.post_shift += 8; + dec_state.shift -= 8; + dec_state.hyb_min >>= 8; + dec_state.hyb_max >>= 8; + } + }, + 0x0A => { // normal stream + validate!(has_samples); + data_pos = br.tell() as usize; + data_len = len; + br.read_skip(len)?; + }, + 0x0C => { + ebits_pos = br.tell() as usize; + ebits_len = len; + br.read_skip(len)?; + }, + 0x0E => return Err(DecoderError::NotImplemented), // DSD + _ => { br.read_skip(len)?; }, + }; + if (len & 1) != 0 { + br.read_skip(1)?; + } + } + validate!(data_pos > 0 && data_len > 0); + if is_hybrid { + validate!(has_hybrid); + } + + let mut br = BitReader::new(&src[data_pos..][..data_len], BitReaderMode::LE); + let mut ebr = BitReader::new(&src[ebits_pos..][..ebits_len], BitReaderMode::LE); + if is_mono { + let is_fstereo = (hdr.flags & WV_FLAG_FALSE_STEREO) != 0; + match abuf { + NABufferType::AudioI16(ref mut adata) => { + let off0 = adata.get_offset(start_ch); + let off1 = adata.get_offset(start_ch + 1); + let dst = adata.get_data_mut().unwrap(); + let crc = if !is_hybrid { + unpack_mono(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, &mut dst[off0..], hdr.block_samples as usize)? + } else { + unpack_mono_hyb(&mut br, &mut ebr, &mut dec_state, &mut + self.dstate, &mut dst[off0..], hdr.block_samples as usize)? + }; + if crc != hdr.crc { + return Err(DecoderError::ChecksumError); + } + if is_fstereo { + for i in 0..(hdr.block_samples as usize) { + dst[off1 + i] = dst[off0 + i]; + } + } + }, + NABufferType::AudioI32(ref mut adata) => { + let off0 = adata.get_offset(start_ch); + let off1 = adata.get_offset(start_ch + 1); + let dst = adata.get_data_mut().unwrap(); + let crc = if !is_hybrid { + unpack_mono(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, &mut dst[off0..], hdr.block_samples as usize)? + } else { + unpack_mono_hyb(&mut br, &mut ebr, &mut dec_state, &mut + self.dstate, &mut dst[off0..], hdr.block_samples as usize)? + }; + if crc != hdr.crc { + return Err(DecoderError::ChecksumError); + } + if is_fstereo { + for i in 0..(hdr.block_samples as usize) { + dst[off1 + i] = dst[off0 + i]; + } + } + }, + _ => unreachable!(), + } + } else { + let is_joint = (hdr.flags & WV_FLAG_JSTEREO) != 0; + match abuf { + NABufferType::AudioI16(ref mut adata) => { + let off0 = adata.get_offset(start_ch); + let off1 = adata.get_offset(start_ch + 1); + let dst = adata.get_data_mut().unwrap(); + let crc = if !is_hybrid { + unpack_stereo(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, dst, off0, off1, hdr.block_samples as usize, is_joint)? + } else { + unpack_stereo_hyb(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, dst, off0, off1, hdr.block_samples as usize, is_joint)? + }; + if crc != hdr.crc { + return Err(DecoderError::ChecksumError); + } + }, + NABufferType::AudioI32(ref mut adata) => { + let off0 = adata.get_offset(start_ch); + let off1 = adata.get_offset(start_ch + 1); + let dst = adata.get_data_mut().unwrap(); + let crc = if !is_hybrid { + unpack_stereo(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, dst, off0, off1, hdr.block_samples as usize, is_joint)? + } else { + unpack_stereo_hyb(&mut br, &mut ebr, &mut dec_state, &mut self.dstate, dst, off0, off1, hdr.block_samples as usize, is_joint)? + }; + if crc != hdr.crc { + return Err(DecoderError::ChecksumError); + } + }, + _ => unreachable!(), + } + } + + Ok(()) + } +} + +impl NADecoder for WavPackDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + if let Some(buf) = info.get_extradata() { + let mut channels = 0; + let mut decl_channels = 0; + let mut channel_map = 0; + let mut off = 0; + while off < buf.len() { + let hdr = WVHeader::parse(&buf[off..])?; + if (hdr.flags & (WV_FLAG_FLOATS | WV_FLAG_DSD_AUDIO)) != 0 { + return Err(DecoderError::NotImplemented); + } + self.header = hdr; + off += WV_HEADER_SIZE; + let size = hdr.get_size(); + let mut mr = MemoryReader::new_read(&buf[off..][..size]); + let mut br = ByteReader::new(&mut mr); + while br.left() > 0 { + let (id, len) = get_subblock(&mut br)?; + match id { + 0xD => { + validate!(len > 1); + decl_channels = br.read_byte()?; + if decl_channels == 0 { + return Err(DecoderError::NotImplemented); + } + channel_map = match len { + 2 => u32::from(br.read_byte()?), + 3 => u32::from(br.read_u16le()?), + 4 => br.read_u24le()?, + 5 => br.read_u32le()?, + _ => return Err(DecoderError::NotImplemented), + }; + }, + _ => br.read_skip(len)?, + }; + if (len & 1) != 0 { + br.read_skip(1)?; + } + } + channels += hdr.get_num_channels(); + + if hdr.is_end_block() { + break; + } + off += size; + } + if decl_channels != 0 { + validate!(decl_channels == channels); + } + self.chmap = if channel_map != 0 { + NAChannelMap::from_ms_mapping(channel_map) + } else if channels == 1 { + NAChannelMap::from_str("C").unwrap() + } else if channels == 2 { + NAChannelMap::from_str("L,R").unwrap() + } else { + return Err(DecoderError::NotImplemented); + }; + let bsamps = if self.header.block_samples == 0 { + self.header.get_sample_rate() + } else { + self.header.block_samples + } as usize; + + let bits = self.header.get_bits(); + let fmt = if (self.header.flags & WV_FLAG_FLOATS) != 0 { + SND_F32P_FORMAT + } else if bits <= 16 { + SND_S16P_FORMAT + } else { + SND_S32P_FORMAT + }; + + self.ainfo = NAAudioInfo::new(self.header.get_sample_rate(), channels, fmt, bsamps); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + if let NACodecTypeInfo::Audio(_) = info.get_properties() { + let pktbuf = pkt.get_buffer(); + validate!(pktbuf.len() > WV_HEADER_SIZE); + let refhdr = WVHeader::parse(&pktbuf)?; + + if refhdr.block_samples == 0 { + let mut frm = NAFrame::new_from_pkt(pkt, info, NABufferType::None); + frm.set_frame_type(FrameType::Skip); + frm.set_keyframe(false); + return Ok(frm.into_ref()); + } + + let mut abuf = alloc_audio_buffer(self.ainfo, refhdr.block_samples as usize, self.chmap.clone())?; + let mut start_ch = 0; + let mut roff = 0; + let mut first = true; + let mut refhdr = WVHeader::default(); + loop { + let hdr = WVHeader::parse(&pktbuf[roff..])?; + if first { + validate!(hdr.is_start_block()); + validate!(self.header.stream_eq(&hdr)); + refhdr = hdr; + first = false; + } else { + validate!(refhdr.block_eq(&hdr)); + } + roff += WV_HEADER_SIZE; + let blk_size = hdr.get_size(); + self.decode_block(&hdr, &pktbuf[roff..][..blk_size], start_ch, &mut abuf)?; + roff += blk_size; + if hdr.is_end_block() { + break; + } + start_ch += hdr.get_num_channels() as usize; + } + let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); + frm.set_duration(Some(u64::from(refhdr.block_samples))); + Ok(frm.into_ref()) + } else { + Err(DecoderError::InvalidData) + } + } + fn flush(&mut self) { + } +} + +impl NAOptionHandler for WavPackDecoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { + Box::new(WavPackDecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::llaudio_register_all_decoders; + use crate::llaudio_register_all_demuxers; + #[test] + fn test_wavpack_8bit() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/8bit-partial.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0x8157bf0f, 0xeb441905, 0xeb6b815d, 0x113480a8])); + } + #[test] + fn test_wavpack_12bit() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/12bit-partial.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xe5faf18c, 0xbf2d3b12, 0x5b0b8f00, 0x162b805a])); + } + #[test] + fn test_wavpack_16bit() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/16bit-partial.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xaf31b252, 0xdf8b282a, 0x2dc38947, 0xf64c68a1])); + } + #[test] + fn test_wavpack_24bit() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/24bit-partial.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0xf5649972, 0xfe757241, 0x383d5ded, 0x0176a75b])); + } + #[test] + fn test_wavpack_hybrid() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/4.0_16-bit.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0x9cfa469a, 0x54af50e1, 0xe45434d1, 0x1bf987e2])); + } + #[test] + fn test_wavpack_hybrid_32bit() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + llaudio_register_all_decoders(&mut dec_reg); + + test_decoding("wavpack", "wavpack", "assets/LLaudio/wv/4.0_32-bit_int.wv", Some(100000), &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0x21415549, 0xf48ddb55, 0xef5c4e7f, 0xa48d5ab9])); + } +} + +const WV_EXP_TABLE: [u8; 256] = [ + 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, + 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, + 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, + 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, + 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, + 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, + 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, + 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, + 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, + 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff +]; +const WV_LOG_TABLE: [u8; 256] = [ + 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, + 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, + 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, + 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, + 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, + 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, + 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, + 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, + 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, + 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, + 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, + 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, + 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff +]; diff --git a/nihav-llaudio/src/demuxers/ape.rs b/nihav-llaudio/src/demuxers/ape.rs new file mode 100644 index 0000000..2969c78 --- /dev/null +++ b/nihav-llaudio/src/demuxers/ape.rs @@ -0,0 +1,267 @@ +use nihav_core::frame::*; +use nihav_core::demuxers::*; + +#[derive(Clone,Copy)] +struct Frame { + off: u32, + size: u32, + bits_off: u8, +} + +struct APEDemuxer<'a> { + src: &'a mut ByteReader<'a>, + cur_frame: usize, + frames: Vec, + normal_blocks: u32, + last_blocks: u32, + truncated: bool, +} + +impl<'a> APEDemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + Self { + src: io, + cur_frame: 0, + frames: Vec::new(), + normal_blocks: 0, + last_blocks: 0, + truncated: false, + } + } +} + +impl<'a> DemuxCore<'a> for APEDemuxer<'a> { + fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> { + let src = &mut self.src; + + let tag = src.read_tag()?; + validate!(&tag == b"MAC "); + let version = src.read_u16le()?; + validate!(version >= 3800 && version <= 3990); + + let seektab_len; + let _wavtail_len; + let compr_type; + let flags; + let blocksperframe; + let finalblocks; + let nframes; + let bits; + let channels; + let srate; + if version >= 3980 { + src.read_skip(2)?; + let descriptor_len = src.read_u32le()? as usize; + let header_len = src.read_u32le()? as usize; + validate!(header_len == 24); + seektab_len = src.read_u32le()? as usize; + let _wavheader_len = src.read_u32le()? as usize; + let _audio_len = src.read_u64le()?; + _wavtail_len = src.read_u32le()? as usize; + src.read_skip(16)?; // unpacked data MD5 + if descriptor_len > 52 { + src.read_skip(descriptor_len - 52)?; + } + + compr_type = src.read_u16le()?; + flags = src.read_u16le()?; + blocksperframe = src.read_u32le()?; + finalblocks = src.read_u32le()?; + nframes = src.read_u32le()? as usize; + bits = src.read_u16le()?; + channels = src.read_u16le()?; + srate = src.read_u32le()?; + } else { + compr_type = src.read_u16le()?; + flags = src.read_u16le()?; + channels = src.read_u16le()?; + srate = src.read_u32le()?; + + let wavheader_len = src.read_u32le()? as usize; + _wavtail_len = src.read_u32le()? as usize; + nframes = src.read_u32le()? as usize; + finalblocks = src.read_u32le()?; + if (flags & 0x04) != 0 { + src.read_u32le()?; // peak level + } + if (flags & 0x10) != 0 { + seektab_len = src.read_u32le()? as usize * 4; + } else { + seektab_len = nframes * 4; + } + + if (flags & 0x01) != 0 { + bits = 8; + } else if (flags & 0x08) != 0 { + bits = 24; + } else { + bits = 16; + } + + blocksperframe = 9216 * if version >= 3950 { + 32 + } else if (version >= 3900) || ((version >= 3800) && (compr_type >= 4000)) { + 8 + } else { + 1 + }; + + if (flags & 0x20) == 0 { + src.read_skip(wavheader_len)?; + } + } + validate!(srate > 0); + validate!(channels > 0 && channels < 256); + validate!(bits > 0 && bits <= 32); + validate!(nframes > 0 && nframes < (1 << 28)); + validate!(seektab_len == nframes * 4); + + self.frames = Vec::with_capacity(nframes); + self.normal_blocks = blocksperframe; + self.last_blocks = finalblocks; + + seek_index.mode = SeekIndexMode::Present; + let first_off = src.peek_u32le()?; + validate!(u64::from(first_off) >= src.tell() + ((nframes * 4) as u64)); + let mut last_off = first_off - 1; + for i in 0..nframes { + let off = src.read_u32le()?; + validate!(off > last_off); + let diff = (off - first_off) & 3; + self.frames.push(Frame { + off: off - diff, + size: 0, + bits_off: (diff as u8) * 8, + }); + + last_off = off; + + let time = (i as u64) * u64::from(blocksperframe) * 1000 / u64::from(srate); + seek_index.add_entry(0, SeekEntry { time, pts: i as u64, pos: i as u64 }); + } + if version < 3810 { + for frame in self.frames.iter_mut() { + let bits = src.read_byte()?; + validate!(bits < 32); + frame.bits_off += bits; + } + } + src.seek(SeekFrom::End(0))?; + let fsize = src.tell(); + validate!(fsize > u64::from(self.frames[0].off)); + self.truncated = u64::from(self.frames[self.frames.len() - 1].off) >= fsize; + if self.truncated { + let mut valid_frames = self.frames.len(); + for frame in self.frames.iter_mut().rev() { + if u64::from(frame.off) >= fsize { + valid_frames -= 1; + } + } + self.frames.truncate(valid_frames); + validate!(!self.frames.is_empty()); + self.truncated = true; + } + let mut last_off = fsize as u32; + for frame in self.frames.iter_mut().rev() { + frame.size = last_off - frame.off; + last_off = frame.off + (if frame.bits_off > 0 { 4 } else { 0 }); + } + + let mut hdr = vec![0u8; 16]; + write_u16le(&mut hdr[0..], version)?; + write_u16le(&mut hdr[2..], compr_type)?; + write_u16le(&mut hdr[4..], flags)?; + hdr[6] = channels as u8; + hdr[7] = bits as u8; + write_u32le(&mut hdr[8..], srate)?; + write_u32le(&mut hdr[12..], blocksperframe)?; + + let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 1); + let ainfo = NACodecInfo::new("ape", NACodecTypeInfo::Audio(ahdr), Some(hdr)); + strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, blocksperframe, srate)).unwrap(); + + self.cur_frame = 0; + + Ok(()) + } + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + if self.cur_frame >= self.frames.len() { + return Err(DemuxerError::EOF); + } + + let size = self.frames[self.cur_frame].size as usize; + let off = self.frames[self.cur_frame].off; + let bits = self.frames[self.cur_frame].bits_off; + let nblocks = if (self.cur_frame < self.frames.len() - 1) || self.truncated { self.normal_blocks } else { self.last_blocks }; + + self.src.seek(SeekFrom::Start(off.into()))?; + + let mut buf = vec![0u8; size + 8]; + write_u32le(&mut buf[0..], nblocks)?; + buf[4] = bits; + self.src.read_buf(&mut buf[8..])?; + + let stream = strmgr.get_stream(0).unwrap(); + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, tb_num, tb_den); + let pkt = NAPacket::new(stream, ts, true, buf); + + self.cur_frame += 1; + + Ok(pkt) + } + fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> { + let ret = seek_index.find_pos(time); + if ret.is_none() { + return Err(DemuxerError::SeekError); + } + let seek_info = ret.unwrap(); + self.cur_frame = seek_info.pts as usize; + if self.cur_frame >= self.frames.len() { + return Err(DemuxerError::SeekError); + } + + Ok(()) + } +} + +impl<'a> NAOptionHandler for APEDemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub struct APEDemuxerCreator { } + +impl DemuxerCreator for APEDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(APEDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "ape" } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fs::File; + + #[test] + fn test_ape_demux() { + let mut file = File::open("assets/LLaudio/ape/luckynight.ape").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = APEDemuxer::new(&mut br); + let mut sm = StreamManager::new(); + let mut si = SeekIndex::new(); + dmx.open(&mut sm, &mut si).unwrap(); + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if (e as i32) == (DemuxerError::EOF as i32) { break; } + panic!("error"); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } +} diff --git a/nihav-llaudio/src/demuxers/flac.rs b/nihav-llaudio/src/demuxers/flac.rs new file mode 100644 index 0000000..f19ce56 --- /dev/null +++ b/nihav-llaudio/src/demuxers/flac.rs @@ -0,0 +1,242 @@ +use nihav_core::frame::*; +use nihav_core::demuxers::*; + +struct FLACDemuxer<'a> { + src: &'a mut ByteReader<'a>, + data_start: u64, + tot_samples: u64, + cur_samples: u64, + blk_samples: u16, + min_size: usize, + max_size: usize, +} + +impl<'a> FLACDemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + Self { + src: io, + data_start: 0, + tot_samples: 0, + cur_samples: 0, + blk_samples: 0, + min_size: 0, + max_size: 0, + } + } +} + +fn update_crc16(crc: u16, byte: u8) -> u16 { + (crc << 8) ^ CRC16_TABLE[(((crc >> 8) as u8) ^ byte) as usize] +} + +fn read_utf8(src: &[u8]) -> DemuxerResult { + if (src[0] & 0x80) == 0 { + return Ok(u32::from(src[0])); + } + let len = (!src[0]).leading_zeros() as usize; + validate!(len != 1 && len <= 5 && src.len() >= len); + let mut val = u32::from(src[0] & 0x1F); + for byte in src.iter().take(len).skip(1) { + validate!((*byte & 0xC0) == 0x80); + val = (val << 6) | u32::from(*byte & 0x3F); + } + Ok(val) +} + +impl<'a> DemuxCore<'a> for FLACDemuxer<'a> { + fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> { + let tag = self.src.read_tag()?; + validate!(&tag == b"fLaC"); + let mut streaminfo: Vec = Vec::new(); + let mut srate = 0u32; + let mut channels = 0u8; + loop { + let id1 = self.src.read_byte()?; + let len = self.src.read_u24be()? as usize; + let id = id1 & 0x7F; + + match id { + 0x00 => { + validate!(len >= 34); + streaminfo = vec![0u8; len]; + self.src.read_buf(&mut streaminfo)?; + let min_bs = read_u16be(&streaminfo[0..])?; + let max_bs = read_u16be(&streaminfo[2..])?; + if min_bs == max_bs { + self.blk_samples = max_bs; + } + self.min_size = read_u24be(&streaminfo[4..])? as usize; + self.max_size = read_u24be(&streaminfo[7..])? as usize; + let word = read_u24be(&streaminfo[10..])?; + srate = word >> 4; + channels = (((word >> 1) & 7) + 1) as u8; + self.tot_samples = (u64::from(streaminfo[13] & 0xF) << 32) | u64::from(read_u32be(&streaminfo[14..])?); + }, + 0x03 => { + validate!((len % 18) == 0); + seek_index.mode = SeekIndexMode::Present; + for _ in 0..len / 18 { + let sample = self.src.read_u64be()?; + let offset = self.src.read_u64be()?; + let _nsamps = self.src.read_u16be()?; + let time = sample * 1000 / u64::from(srate.max(1000)); + seek_index.add_entry(0, SeekEntry { time, pts: sample, pos: offset }); + } + }, + _ => self.src.read_skip(len)?, + }; + + if (id1 & 0x80) != 0 { + break; + } + } + self.data_start = self.src.tell(); + validate!(srate != 0); + + let base = if self.blk_samples != 0 { u32::from(self.blk_samples) } else { 1 }; + let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, base as usize); + let ainfo = NACodecInfo::new("flac", NACodecTypeInfo::Audio(ahdr), Some(streaminfo)); + strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, base, srate)).unwrap(); + + Ok(()) + } + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + if self.src.is_eof() || (self.tot_samples != 0 && self.cur_samples == self.tot_samples) { return Err(DemuxerError::EOF); } + let mut buf = Vec::with_capacity(self.min_size); + let mut crc = 0; + for _ in 0..5 { + let byte = self.src.read_byte()?; + buf.push(byte); + crc = update_crc16(crc, byte); + } + let mut ref_crc = self.src.read_u16be()?; + loop { + let byte = self.src.read_byte()?; + let old_byte = (ref_crc >> 8) as u8; + buf.push(old_byte); + ref_crc = (ref_crc << 8) | u16::from(byte); + crc = update_crc16(crc, old_byte); + if buf.len() + 2 >= self.min_size && crc == ref_crc { + let ret = self.src.peek_u16be(); + if ret.is_err() || ((ret.unwrap_or(0) & 0xFFFE) == 0xFFF8) { + buf.push((ref_crc >> 8) as u8); + buf.push(ref_crc as u8); + break; + } + } + if (self.max_size > 0) && (buf.len() > self.max_size) { + return Err(DemuxerError::InvalidData); + } + if buf.len() > (1 << 23) { + return Err(DemuxerError::InvalidData); + } + } + + let (duration, pts) = if self.blk_samples != 0 { + validate!((buf[1] & 1) == 0); + let blkno = u64::from(read_utf8(&buf[4..])?); + self.cur_samples = blkno * u64::from(self.blk_samples); + (u64::from(self.blk_samples), blkno) + } else { + validate!((buf[1] & 1) != 0); + let blksamps = u64::from(read_utf8(&buf[4..])?); + (blksamps, self.cur_samples) + }; + + let stream = strmgr.get_stream(0).unwrap(); + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(pts), None, Some(duration), tb_num, tb_den); + let pkt = NAPacket::new(stream, ts, true, buf); + + self.cur_samples += duration; + + Ok(pkt) + } + fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> { + let ret = seek_index.find_pos(time); + if ret.is_none() { + return Err(DemuxerError::SeekError); + } + let seek_info = ret.unwrap(); + self.cur_samples = seek_info.pts; + self.src.seek(SeekFrom::Start(self.data_start + seek_info.pos))?; + + Ok(()) + } +} + +impl<'a> NAOptionHandler for FLACDemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub struct FLACDemuxerCreator { } + +impl DemuxerCreator for FLACDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(FLACDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "flac" } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fs::File; + + #[test] + fn test_flac_demux() { + let mut file = File::open("assets/LLaudio/luckynight.flac").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = FLACDemuxer::new(&mut br); + let mut sm = StreamManager::new(); + let mut si = SeekIndex::new(); + dmx.open(&mut sm, &mut si).unwrap(); + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if (e as i32) == (DemuxerError::EOF as i32) { break; } + panic!("error"); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } +} + +const CRC16_TABLE: [u16; 256] = [ + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +]; diff --git a/nihav-llaudio/src/demuxers/mod.rs b/nihav-llaudio/src/demuxers/mod.rs new file mode 100644 index 0000000..ce0f012 --- /dev/null +++ b/nihav-llaudio/src/demuxers/mod.rs @@ -0,0 +1,33 @@ +use nihav_core::demuxers::*; + +#[allow(unused_macros)] +macro_rules! validate { + ($a:expr) => { if !$a { println!("check failed at {}:{}", file!(), line!()); return Err(DemuxerError::InvalidData); } }; +} + +#[cfg(feature="demuxer_ape")] +mod ape; +#[cfg(feature="demuxer_flac")] +mod flac; +#[cfg(feature="demuxer_tta")] +mod tta; +#[cfg(feature="demuxer_wavpack")] +mod wavpack; + +const LL_AUDIO_DEMUXERS: &[&DemuxerCreator] = &[ +#[cfg(feature="demuxer_ape")] + &ape::APEDemuxerCreator {}, +#[cfg(feature="demuxer_flac")] + &flac::FLACDemuxerCreator {}, +#[cfg(feature="demuxer_tta")] + &tta::TTADemuxerCreator {}, +#[cfg(feature="demuxer_wavpack")] + &wavpack::WavPackDemuxerCreator {}, +]; + +/// Registers all available demuxers provided by this crate. +pub fn llaudio_register_all_demuxers(rd: &mut RegisteredDemuxers) { + for demuxer in LL_AUDIO_DEMUXERS.iter() { + rd.add_demuxer(*demuxer); + } +} diff --git a/nihav-llaudio/src/demuxers/tta.rs b/nihav-llaudio/src/demuxers/tta.rs new file mode 100644 index 0000000..97ee808 --- /dev/null +++ b/nihav-llaudio/src/demuxers/tta.rs @@ -0,0 +1,140 @@ +use nihav_core::frame::*; +use nihav_core::demuxers::*; + +struct TTADemuxer<'a> { + src: &'a mut ByteReader<'a>, + cur_frame: u32, + nframes: u32, + nsamples: u32, + offtab: Vec, + sizetab: Vec, + framelen: u32, +} + +impl<'a> TTADemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + Self { + src: io, + cur_frame: 0, + nframes: 0, + nsamples: 0, + offtab: Vec::new(), + sizetab: Vec::new(), + framelen: 0, + } + } +} + +impl<'a> DemuxCore<'a> for TTADemuxer<'a> { + fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> { + + let mut hdr = vec![0; 22]; + self.src.read_buf(&mut hdr)?; + + validate!(&hdr[..4] == b"TTA1"); + let _afmt = read_u16le(&hdr[4..])?; + let channels = read_u16le(&hdr[6..])?; + validate!(channels > 0 && channels < 256); + let bpp = read_u16le(&hdr[8..])?; + validate!(bpp > 0 && bpp <= 32); + let srate = read_u32le(&hdr[10..])?; + validate!(srate > 256 && srate < 1048576); + self.nsamples = read_u32le(&hdr[14..])?; + validate!(self.nsamples > 0); + let _crc = read_u32le(&hdr[18..])?; + + self.framelen = srate * 256 / 245; + + self.nframes = (self.nsamples + self.framelen - 1) / self.framelen; + + seek_index.mode = SeekIndexMode::Present; + let mut off = u64::from(self.nframes) * 4 + 4 + 22; + let mut cur_time = 0; + for pts in 0..self.nframes { + let fsize = self.src.read_u32le()?; + self.sizetab.push(fsize); + self.offtab.push(off); + let time = u64::from(cur_time) * 1000 / u64::from(srate); + seek_index.add_entry(0, SeekEntry { time, pts: u64::from(pts), pos: off }); + off += u64::from(fsize); + cur_time += self.framelen; + } + + let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 1); + let ainfo = NACodecInfo::new("tta", NACodecTypeInfo::Audio(ahdr), Some(hdr)); + strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, self.framelen, srate)).unwrap(); + + self.cur_frame = 0; + + Ok(()) + } + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + if self.cur_frame >= self.nframes { + return Err(DemuxerError::EOF); + } + + let size = self.sizetab[self.cur_frame as usize] as usize; + let off = self.offtab[self.cur_frame as usize]; + self.src.seek(SeekFrom::Start(off))?; + + let stream = strmgr.get_stream(0).unwrap(); + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(self.cur_frame.into()), None, None, tb_num, tb_den); + let pkt = self.src.read_packet(stream, ts, true, size)?; + + self.cur_frame += 1; + + Ok(pkt) + } + fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> { + let ret = seek_index.find_pos(time); + if ret.is_none() { + return Err(DemuxerError::SeekError); + } + let seek_info = ret.unwrap(); + self.cur_frame = seek_info.pts as u32; + + Ok(()) + } +} + +impl<'a> NAOptionHandler for TTADemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub struct TTADemuxerCreator { } + +impl DemuxerCreator for TTADemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(TTADemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "tta" } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fs::File; + + #[test] + fn test_tta_demux() { + let mut file = File::open("assets/LLaudio/luckynight.tta").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = TTADemuxer::new(&mut br); + let mut sm = StreamManager::new(); + let mut si = SeekIndex::new(); + dmx.open(&mut sm, &mut si).unwrap(); + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if (e as i32) == (DemuxerError::EOF as i32) { break; } + panic!("error"); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } +} diff --git a/nihav-llaudio/src/demuxers/wavpack.rs b/nihav-llaudio/src/demuxers/wavpack.rs new file mode 100644 index 0000000..9cfbba8 --- /dev/null +++ b/nihav-llaudio/src/demuxers/wavpack.rs @@ -0,0 +1,296 @@ +use nihav_core::frame::*; +use nihav_core::demuxers::*; + +const SAMPLE_RATES: [u32; 15] = [ + 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000, 192000 +]; +const WV_FLAG_MONO: u32 = 1 << 2; +//const WV_FLAG_HYBRID: u32 = 1 << 3; +//const WV_FLAG_JSTEREO: u32 = 1 << 4; +//const WV_FLAG_CH_DECORR: u32 = 1 << 5; +//const WV_FLAG_HYB_NOISE_SHAPING: u32 = 1 << 6; +const WV_FLAG_FLOATS: u32 = 1 << 7; +//const WV_FLAG_EXT_INTEGERS: u32 = 1 << 8; +//const WV_FLAG_HYB_BITRATE: u32 = 1 << 9; +//const WV_FLAG_HYB_BALANCED_NOISE: u32 = 1 << 10; +const WV_FLAG_START_BLOCK: u32 = 1 << 11; +const WV_FLAG_END_BLOCK: u32 = 1 << 12; +//const WV_FLAG_HAS_CRC: u32 = 1 << 28; +const WV_FLAG_FALSE_STEREO: u32 = 1 << 30; +//const WV_FLAG_DSD_AUDIO: u32 = 1 << 31; + +const WV_STREAM_FLAGS: u32 = 0x8000018B; + +#[derive(Clone,Copy,Default)] +struct WVHeader { + size: usize, + ver: u16, + tot_samples: u64, + block_index: u64, + block_samples: u32, + flags: u32, + crc: u32, +} + +const WV_HEADER_SIZE: usize = 32; + +impl WVHeader { + fn parse(src: &[u8]) -> DemuxerResult { + let mut mr = MemoryReader::new_read(src); + let mut br = ByteReader::new(&mut mr); + let tag = br.read_tag()?; + validate!(&tag == b"wvpk"); + let mut hdr = Self::default(); + hdr.size = br.read_u32le()? as usize; + validate!(hdr.size >= 24); + hdr.ver = br.read_u16le()?; + validate!(hdr.ver >= 0x402 || hdr.ver <= 0x410); + let top_idx = br.read_byte()?; + let top_samps = br.read_byte()?; + hdr.tot_samples = u64::from(br.read_u32le()?) | (u64::from(top_samps) << 32); + hdr.block_index = u64::from(br.read_u32le()?) | (u64::from(top_idx) << 32); + hdr.block_samples = br.read_u32le()?; + hdr.flags = br.read_u32le()?; + hdr.crc = br.read_u32le()?; + Ok(hdr) + } + fn stream_eq(&self, rval: &Self) -> bool { + self.ver == rval.ver && + (self.flags & WV_STREAM_FLAGS) == (rval.flags & WV_STREAM_FLAGS) + } + fn block_eq(&self, rval: &Self) -> bool { + self.stream_eq(rval) && self.tot_samples == rval.tot_samples && + self.block_index == rval.block_index && + self.block_samples == rval.block_samples + } + fn is_start_block(&self) -> bool { + (self.flags & WV_FLAG_START_BLOCK) != 0 + } + fn is_end_block(&self) -> bool { + (self.flags & WV_FLAG_END_BLOCK) != 0 + } + fn get_num_channels(&self) -> u8 { + if (self.flags & WV_FLAG_MONO) != 0 && (self.flags & WV_FLAG_FALSE_STEREO) == 0 { 1 } else { 2 } + } + fn get_sample_rate(&self) -> u32 { + let idx = ((self.flags >> 23) & 0xF) as usize; + if idx != 15 { + SAMPLE_RATES[idx] + } else { + 0 + } + } + fn get_size(&self) -> usize { + self.size - (WV_HEADER_SIZE - 8) + } +} + +#[derive(Clone,Copy,Default)] +struct FrameSeekInfo { + off: u64, + samplepos: u64, +} + +struct WavPackDemuxer<'a> { + src: &'a mut ByteReader<'a>, + samplepos: u64, + nsamples: u64, + first_blocks: Option<(WVHeader, Vec)>, + srate: u32, + known_frames: Vec, +} + +impl<'a> WavPackDemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + Self { + src: io, + samplepos: 0, + nsamples: 0, + first_blocks: None, + srate: 0, + known_frames: Vec::new(), + } + } + fn read_blocks(&mut self) -> DemuxerResult<(WVHeader, Vec)> { + let mut hdrbuf = [0u8; WV_HEADER_SIZE]; + let mut buf: Vec = Vec::new(); + let mut first = true; + let mut refhdr = WVHeader::default(); + loop { + self.src.read_buf(&mut hdrbuf)?; + let hdr = WVHeader::parse(&hdrbuf)?; + if first { + validate!(hdr.is_start_block()); + refhdr = hdr; + first = false; + } else { + validate!(refhdr.block_eq(&hdr)); + } + buf.extend_from_slice(&hdrbuf); + let pos = buf.len(); + buf.resize(pos + hdr.get_size(), 0); + self.src.read_buf(&mut buf[pos..])?; + + if hdr.is_end_block() { + break; + } + } + Ok((refhdr, buf)) + } +} + +impl<'a> DemuxCore<'a> for WavPackDemuxer<'a> { + fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> { + + let (hdr, buf) = self.read_blocks()?; + + let srate = hdr.get_sample_rate(); + validate!(srate != 0); + let channels = if !hdr.is_end_block() { + let mut ch_count = 0; + let mut off = 0; + loop { + let hdr = WVHeader::parse(&buf[off..]).unwrap(); + off += WV_HEADER_SIZE + hdr.get_size(); + ch_count += hdr.get_num_channels(); + if hdr.is_end_block() { + break; + } + } + ch_count + } else { + hdr.get_num_channels() + }; + + self.nsamples = hdr.tot_samples; + + let mut fmt = SND_S16P_FORMAT; + if (hdr.flags & WV_FLAG_FLOATS) != 0 { + fmt.float = true; + } else { + fmt.bits = (((hdr.flags & 3) + 1) * 8) as u8; + } + + let ahdr = NAAudioInfo::new(srate, channels, SND_S16P_FORMAT, 1); + let ainfo = NACodecInfo::new("wavpack", NACodecTypeInfo::Audio(ahdr), Some(buf.clone())); + strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, srate)).unwrap(); + seek_index.mode = SeekIndexMode::Automatic; + self.srate = srate; + self.known_frames = Vec::with_capacity(((self.nsamples + u64::from(srate) - 1) / u64::from(srate)) as usize); + self.known_frames.push(FrameSeekInfo { off: 0, samplepos: hdr.block_index }); + + self.first_blocks = Some((hdr, buf)); + Ok(()) + } + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + if self.first_blocks.is_some() { + let mut fb = None; + std::mem::swap(&mut fb, &mut self.first_blocks); + let (refhdr, buf) = fb.unwrap(); + let stream = strmgr.get_stream(0).unwrap(); + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(self.samplepos), None, None, tb_num, tb_den); + let pkt = NAPacket::new(stream, ts, true, buf); + + self.samplepos += u64::from(refhdr.block_samples); + + return Ok(pkt); + } + if self.samplepos == self.nsamples { + return Err(DemuxerError::EOF); + } + let cur_off = self.src.tell(); + let cur_spos = self.samplepos; + let (refhdr, buf) = self.read_blocks()?; + + let stream = strmgr.get_stream(0).unwrap(); + let (tb_num, tb_den) = stream.get_timebase(); + let ts = NATimeInfo::new(Some(self.samplepos), None, None, tb_num, tb_den); + let pkt = NAPacket::new(stream, ts, true, buf); + + self.samplepos += u64::from(refhdr.block_samples); + if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).samplepos < cur_spos { + self.known_frames.push(FrameSeekInfo{off: cur_off, samplepos: cur_spos }); + } + + Ok(pkt) + } + fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { + self.first_blocks = None; + if let NATimePoint::Milliseconds(ms) = time { + let samppos = ms * u64::from(self.srate) / 1000; + if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).samplepos >= samppos { + for point in self.known_frames.iter().rev() { + if point.samplepos <= samppos { + self.src.seek(SeekFrom::Start(point.off))?; + self.samplepos = point.samplepos; + return Ok(()); + } + } + } else { + let mut hdrbuf = [0u8; WV_HEADER_SIZE]; + loop { + self.src.peek_buf(&mut hdrbuf)?; + let hdr = WVHeader::parse(&hdrbuf)?; + if hdr.is_start_block() { + self.known_frames.push(FrameSeekInfo{off: self.src.tell(), samplepos: hdr.block_index }); + if hdr.block_index <= samppos && hdr.block_index + u64::from(hdr.block_samples) > samppos { + self.samplepos = hdr.block_index; + return Ok(()); + } + if hdr.block_index > samppos { + break; + } + } + self.src.read_skip(WV_HEADER_SIZE + hdr.get_size())? + } + } + Err(DemuxerError::SeekError) + } else { + Err(DemuxerError::NotPossible) + } + } +} + +impl<'a> NAOptionHandler for WavPackDemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + + +pub struct WavPackDemuxerCreator { } + +impl DemuxerCreator for WavPackDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(WavPackDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "wavpack" } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fs::File; + + #[test] + fn test_wavpack_demux() { + let mut file = File::open("assets/LLaudio/wv/false_stereo.wv").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = WavPackDemuxer::new(&mut br); + let mut sm = StreamManager::new(); + let mut si = SeekIndex::new(); + dmx.open(&mut sm, &mut si).unwrap(); + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if (e as i32) == (DemuxerError::EOF as i32) { break; } + panic!("error"); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } +} diff --git a/nihav-llaudio/src/lib.rs b/nihav-llaudio/src/lib.rs new file mode 100644 index 0000000..abe4694 --- /dev/null +++ b/nihav-llaudio/src/lib.rs @@ -0,0 +1,10 @@ +extern crate nihav_core; +extern crate nihav_codec_support; + +#[allow(clippy::unreadable_literal)] +#[allow(clippy::verbose_bit_mask)] +mod codecs; +#[allow(clippy::unreadable_literal)] +mod demuxers; +pub use crate::codecs::llaudio_register_all_decoders; +pub use crate::demuxers::llaudio_register_all_demuxers; diff --git a/nihav-registry/src/detect.rs b/nihav-registry/src/detect.rs index 6f67fbd..210d000 100644 --- a/nihav-registry/src/detect.rs +++ b/nihav-registry/src/detect.rs @@ -254,6 +254,28 @@ const DETECTORS: &[DetectConditions] = &[ extensions: ".smk", conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b"SMK2"), &CC::Str(b"SMK4"))}], }, + DetectConditions { + demux_name: "ape", + extensions: ".ape", + conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"MAC ") }, + CheckItem{offs: 4, cond: &CC::In(Arg::U16LE(3800), Arg::U16LE(3990))}], + }, + DetectConditions { + demux_name: "flac", + extensions: ".flac", + conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"fLaC") }], + }, + DetectConditions { + demux_name: "tta", + extensions: ".tta", + conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"TTA1") }], + }, + DetectConditions { + demux_name: "wavpack", + extensions: ".wv", + conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"wvpk") }, + CheckItem{offs: 8, cond: &CC::In(Arg::U16LE(0x402), Arg::U16LE(0x410))}], + }, DetectConditions { demux_name: "vivo", extensions: ".viv", diff --git a/nihav-registry/src/register.rs b/nihav-registry/src/register.rs index 0accdd4..fdf9e83 100644 --- a/nihav-registry/src/register.rs +++ b/nihav-registry/src/register.rs @@ -137,6 +137,10 @@ macro_rules! desc { CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio, caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY } }); + (audio-hyb; $n:expr, $fn:expr) => ({ + CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio, + caps: CODEC_CAP_HYBRID } + }); } /// Returns codec description for the provided codec short name if it is found. @@ -245,6 +249,11 @@ static CODEC_REGISTER: &'static [CodecDescription] = &[ desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER), desc!(audio; "g723.1", "ITU G.723.1"), desc!(audio; "siren", "Polycom Siren"), + + desc!(audio-ll; "ape", "Monkey's Audio"), + desc!(audio-ll; "flac", "Free Lossless Audio Codec"), + desc!(audio-ll; "tta", "True Audio codec"), + desc!(audio-hyb; "wavpack", "WavPack"), ]; static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[ -- 2.30.2