use nihav_core::io::bitreader::*;
use nihav_core::io::codebook::*;
use nihav_core::io::intcode::*;
-use nihav_core::dsp::fft::*;
-use nihav_core::dsp::mdct::IMDCT;
+use nihav_codec_support::dsp::fft::*;
+use nihav_codec_support::dsp::mdct::IMDCT;
use std::str::FromStr;
let mut cur_band = 0;
let mut scale = 0;
let mut first = true;
- for wg in self.win_grp.iter().take(self.windows) {
- if *wg {
+ for wg in 0..self.windows {
+ if self.win_grp[wg] {
for _ in 0..bands {
if self.cbs[cur_band] == 0 {
- self.scales[cur_band] = 0;
- } else {
- if first {
- scale = br.read(7)? as i16;
- first = false
- } else {
- scale += br.read_cb(&self.codebooks.scale_cb)? as i16;
- validate!((scale >= 0) && (scale < 128));
+ let mut all_zero = true;
+ let mut band2 = cur_band;
+ for wg2 in wg + 1..self.windows {
+ if self.win_grp[wg2] {
+ break;
+ }
+ band2 += bands;
+ if self.cbs[band2] != 0 {
+ all_zero = false;
+ break;
+ }
+ }
+ if all_zero {
+ self.scales[cur_band] = 0;
+ cur_band += 1;
+ continue;
}
- self.scales[cur_band] = scale as u8;
}
+ if first {
+ scale = br.read(7)? as i16;
+ first = false;
+ } else {
+ scale += i16::from(br.read_cb(&self.codebooks.scale_cb)?);
+ validate!((scale >= 0) && (scale < 128));
+ }
+ self.scales[cur_band] = scale as u8;
cur_band += 1;
}
} else {
}
Ok(())
}
+ #[allow(clippy::cognitive_complexity)]
fn synth_channel(&mut self, chno: usize, dst: &mut [f32]) {
let coeffs = &mut self.coeffs[chno];
let delay = &mut self.delay[chno];
}
},
2 | 7 => {
- self.imdct_long.imdct(coeffs, &mut self.tmp);
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
- overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &self.tmp[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
- for i in SHORT_WIN_POINT1..COEFFS {
- dst[i] = self.tmp[i - SHORT_WIN_POINT1 + 128];
- }
- delay.copy_from_slice(&self.tmp[COEFFS..]);
+ self.imdct_long.imdct_half(coeffs, &mut self.ew_buf);
},
3 => {
for (ain, aout) in coeffs.chunks(128).zip(self.tmp.chunks_mut(256)) {
for i in 0..SHORT_WIN_POINT1 {
delay[i] = self.ew_buf[SHORT_WIN_POINT1 + i];
}
- for i in SHORT_WIN_POINT1..COEFFS {
- delay[i] = 0.0;
+ for i in COEFFS/2..COEFFS {
+ delay[i] = delay[COEFFS - 1 - i];
}
},
4 => {
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
if !self.use_generic {
synth1024(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
} else {
synth_generic(coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz, 1024);
}
- overlap_half(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &self.ew_buf[0..64],
- &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
- for i in SHORT_WIN_POINT1..COEFFS {
- dst[i] = self.ew_buf[i - SHORT_WIN_POINT1 + 64];
- }
- for i in 0..COEFFS/2 {
- delay[i] = self.ew_buf[COEFFS/2 + i];
- }
- for i in COEFFS/2..COEFFS {
- delay[i] = delay[COEFFS - 1 - i];
- }
- },
+ },
5 => {
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
if !self.use_generic {
synth512(&mut self.dsp, coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz);
} else {
synth_generic(coeffs, &mut self.ew_buf, &mut self.tmp, self.is_40khz, 512);
}
- self.imdct_mid.imdct(&coeffs[512..], &mut self.ew_buf[512..]);
- overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &self.ew_buf[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
- for i in SHORT_WIN_POINT1..COEFFS {
- dst[i] = self.ew_buf[i];
- }
- *delay = [0.0; COEFFS];
- for i in 0..SHORT_WIN_POINT1 {
- delay[i] = self.ew_buf[i];
- }
+ self.imdct_mid.imdct_half(&coeffs[512..], &mut self.ew_buf[512..]);
},
6 => {
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
- self.imdct_mid.imdct(coeffs, &mut self.ew_buf);
+ self.imdct_mid.imdct_half(coeffs, &mut self.ew_buf);
if !self.use_generic {
synth512(&mut self.dsp, &coeffs[512..], &mut self.ew_buf[512..], &mut self.tmp, self.is_40khz);
} else {
synth_generic(&coeffs[512..], &mut self.ew_buf[512..], &mut self.tmp, self.is_40khz, 512);
}
- overlap(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &self.ew_buf[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
- &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
- for i in SHORT_WIN_POINT1..COEFFS {
- dst[i] = self.ew_buf[i];
- }
- *delay = [0.0; COEFFS];
- for i in 0..SHORT_WIN_POINT1 {
- delay[i] = self.ew_buf[i];
- }
},
_ => unreachable!(),
};
+ if (self.cur_win == 2) || (self.cur_win >= 4) {
+ for i in 0..SHORT_WIN_POINT0 {
+ dst[i] = delay[i];
+ }
+ overlap_half(&mut dst[SHORT_WIN_POINT0..SHORT_WIN_POINT1],
+ &self.ew_buf[0..64],
+ &delay[SHORT_WIN_POINT0..SHORT_WIN_POINT1], AVC_WIN_SHORT);
+ for i in SHORT_WIN_POINT1..COEFFS {
+ dst[i] = self.ew_buf[i - SHORT_WIN_POINT1 + 64];
+ }
+ for i in 0..COEFFS/2 {
+ delay[i] = self.ew_buf[COEFFS/2 + i];
+ }
+ for i in COEFFS/2..COEFFS {
+ delay[i] = delay[COEFFS - 1 - i];
+ }
+ }
}
}
fn $name(src: &[f32], dst: &mut [f32], step: usize, off: usize, sp: &SynthParams) {
for i in 0..step {
for j in 0..sp.p0 {
- dst[i] += ((src[j] as f64) * $tab[sp.idx][j][i]) as f32;
+ dst[i] += (f64::from(src[j]) * $tab[sp.idx][j][i]) as f32;
}
}
for i in 0..step {
for j in 0..sp.p1 {
- dst[$size - step + i] += ((src[sp.p0 + off + j] as f64) * $tab[sp.idx][sp.p0 + j][i]) as f32;
+ dst[$size - step + i] += (f64::from(src[sp.p0 + off + j]) * $tab[sp.idx][sp.p0 + j][i]) as f32;
}
}
}
{
let mut pos = step - 1;
for _ in 0..off {
- let scale = src[p0] as f64;
+ let scale = f64::from(src[p0]);
p0 += 1;
pos &= size - 1;
for i in 0..pos.min(step) {
(&mut dst[..size]).copy_from_slice(&src[..size]);
let mut order_idx = 0;
synth_recursive(dst, tmpbuf, size, order, &mut order_idx, false);
- for i in 0..COEFFS { dst[i] *= 0.125; }
+ for el in dst.iter_mut().take(COEFFS) { *el *= 0.125; }
}
fn synth1024(dsp: &mut SynthDSP, src: &[f32], dst: &mut [f32], tmpbuf: &mut [f32; COEFFS * 2], is_40khz: bool) {
if self.version == 500 {
abuf = alloc_audio_buffer(self.ainfo, COEFFS, self.chmap.clone())?;
let mut adata = abuf.get_abuf_f32().unwrap();
- let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::BE);
+ let mut br = BitReader::new(src.as_slice(), BitReaderMode::BE);
self.decode_frame(&mut br, &mut adata, 0)?;
} else {
let mut offsets: Vec<usize> = Vec::new();
let mut adata = abuf.get_abuf_f32().unwrap();
let mut aoffset = 0;
for (o, s) in offsets.iter().zip(sizes.iter()) {
- let mut br = BitReader::new(&src[*o..], *s, BitReaderMode::BE);
+ let mut br = BitReader::new(&src[*o..][..*s], BitReaderMode::BE);
self.decode_frame(&mut br, &mut adata, aoffset)?;
aoffset += COEFFS;
}
}
}
-pub fn get_decoder_500() -> Box<dyn NADecoder> {
+impl NAOptionHandler for AVCDecoder {
+ fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
+ fn set_options(&mut self, _options: &[NAOption]) { }
+ fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
+}
+
+pub fn get_decoder_500() -> Box<dyn NADecoder + Send> {
Box::new(AVCDecoder::new(500))
}
-pub fn get_decoder_501() -> Box<dyn NADecoder> {
+pub fn get_decoder_501() -> Box<dyn NADecoder + Send> {
Box::new(AVCDecoder::new(501))
}
mod test {
use nihav_core::codecs::RegisteredDecoders;
use nihav_core::demuxers::RegisteredDemuxers;
- use nihav_core::test::dec_video::*;
- use crate::codecs::duck_register_all_codecs;
- use nihav_commonfmt::demuxers::generic_register_all_demuxers;
+ use nihav_codec_support::test::dec_video::*;
+ use crate::duck_register_all_decoders;
+ use nihav_commonfmt::generic_register_all_demuxers;
#[test]
fn test_avc() {
let mut dmx_reg = RegisteredDemuxers::new();
generic_register_all_demuxers(&mut dmx_reg);
let mut dec_reg = RegisteredDecoders::new();
- duck_register_all_codecs(&mut dec_reg);
+ duck_register_all_decoders(&mut dec_reg);
//let file = "assets/Duck/Cell-140.vp5";
//let file = "assets/Duck/Chocolat-500.vp5";
+ // sample: https://samples.mplayerhq.hu/V-codecs/VP7/potter-500.vp7
let file = "assets/Duck/potter-500.vp7";
- test_decode_audio("avi", file, Some(1500), "avc", &dmx_reg, &dec_reg);
+ test_decode_audio("avi", file, Some(1500), None/*Some("avc")*/, &dmx_reg, &dec_reg);
}
}