X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-game%2Fsrc%2Fcodecs%2Fvmd.rs;h=110548a7917642d84266a666a35a129c6a9201cd;hb=fa57381ec2a3b8c441aa1388492b9ca037cfcf78;hp=c8ef7daa55c5d4f3cc5ef1508b92a0ee341f0889;hpb=3e91c67bfde3462596707d2d82fa6271f8b99301;p=nihav.git diff --git a/nihav-game/src/codecs/vmd.rs b/nihav-game/src/codecs/vmd.rs index c8ef7da..110548a 100644 --- a/nihav-game/src/codecs/vmd.rs +++ b/nihav-game/src/codecs/vmd.rs @@ -335,6 +335,12 @@ impl NADecoder for VMDVideoDecoder { } } +impl NAOptionHandler for VMDVideoDecoder { + 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_video() -> Box { Box::new(VMDVideoDecoder::new()) @@ -435,9 +441,6 @@ impl VMDAudioDecoder { pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize]) } } - fn cvt_u8(val: u8) -> u8 { - val ^ 0x80 - } } impl NADecoder for VMDAudioDecoder { @@ -448,7 +451,7 @@ impl NADecoder for VMDAudioDecoder { let edata = info.get_extradata(); let flags = if let Some(ref buf) = edata { validate!(buf.len() >= 2); - (buf[0] as u16) | ((buf[1] as u16) << 8) + u16::from(buf[0]) | (u16::from(buf[1]) << 8) } else { 0 }; @@ -465,24 +468,27 @@ impl NADecoder for VMDAudioDecoder { self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0); } } else { - fmt = SND_S16P_FORMAT; self.blk_align = ainfo.get_block_len(); if (flags & 0x10) == 0 { + fmt = SND_S16P_FORMAT; self.blk_size = (ainfo.get_block_len() + 1) * channels; self.mode = VMDAudioMode::DPCM; } else { - self.blk_size = (ainfo.get_block_len() + 1) / 2 + 3; + fmt = SND_S16_FORMAT; + self.blk_size = (ainfo.get_block_len() * channels + 1) / 2 + 3 * channels; self.mode = VMDAudioMode::ADPCM; } }; self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len()); - self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone())); + self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo)); self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap(); Ok(()) } else { Err(DecoderError::InvalidData) } } + #[allow(clippy::identity_op)] + #[allow(clippy::cyclomatic_complexity)] fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { let info = pkt.get_stream().get_info(); if let NACodecTypeInfo::Audio(_) = info.get_properties() { @@ -532,10 +538,7 @@ impl NADecoder for VMDAudioDecoder { dst[doff + i] = br.read_byte()?; } } else { - for i in 0..self.blk_size { - let val = Self::cvt_u8(br.read_byte()?); - dst[doff + i] = val; - } + unreachable!(); } doff += self.blk_align * channels; mask >>= 1; @@ -603,6 +606,9 @@ impl NADecoder for VMDAudioDecoder { let mut ima = IMAState::new(); for _ in 0..nblocks { if (mask & 1) != 0 { + for i in 0..self.blk_align { + dst[doff + i] = 0; + } doff += self.blk_align; mask >>= 1; continue; @@ -624,7 +630,35 @@ impl NADecoder for VMDAudioDecoder { mask >>= 1; } } else { - return Err(DecoderError::InvalidData); + let mut mask = mask; + let mut ima1 = IMAState::new(); + let mut ima2 = IMAState::new(); + for _ in 0..nblocks { + if (mask & 1) != 0 { + for i in 0..self.blk_align * 2 { + dst[doff + i] = 0; + } + doff += self.blk_align * 2; + mask >>= 1; + continue; + } + let pred1 = br.read_u16le()? as i16; + let pred2 = br.read_u16le()? as i16; + let step1 = br.read_byte()?; + let step2 = br.read_byte()?; + validate!((step1 as usize) < IMA_STEP_TABLE.len()); + validate!((step2 as usize) < IMA_STEP_TABLE.len()); + ima1.reset(pred1, step1); + ima2.reset(pred2, step2); + for _ in 0..self.blk_align { + let b = br.read_byte()?; + dst[doff] = ima1.expand_sample(b >> 4); + doff += 1; + dst[doff] = ima2.expand_sample(b & 0xF); + doff += 1; + } + mask >>= 1; + } } }, }; @@ -641,6 +675,12 @@ impl NADecoder for VMDAudioDecoder { } } +impl NAOptionHandler for VMDAudioDecoder { + 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_audio() -> Box { Box::new(VMDAudioDecoder::new()) }