1 use nihav_core::codecs::*;
2 use nihav_codec_support::dsp::dct::*;
3 use nihav_codec_support::dsp::fft::*;
4 use nihav_core::io::bitreader::*;
14 const MAX_BANDS: usize = 25;
16 struct BinkAudioDecoder {
24 bands: [usize; MAX_BANDS + 1],
28 delay: [[f32; 256]; 2],
33 fn read_bink_float(br: &mut BitReader) -> DecoderResult<f32> {
34 /*let exp = (br.read(5)? as i8) - 23;
35 let mant = br.read(23)? as u32;
36 let sign = br.read_bool()?;
38 (mant as f32) * ((1 << exp) as f32)
40 (mant as f32) / ((1 << -exp) as f32)
47 let exp = br.read(5)? as u8;
48 let mant = br.read(23)?;
49 let sign = br.read(1)?;
50 let nexp = exp.wrapping_add(0x7E) as u32;
51 let nmant = (mant << 1) & ((1 << 23) - 1);
52 Ok(f32::from_bits((sign << 31) | (nexp << 23) | nmant))
55 fn overlap(a: &[f32], b: &[f32], dst: &mut [f32], len: usize, step: usize) {
57 dst[i] = (a[i] * ((len - i) as f32) + b[i * step] * (i as f32)) / (len as f32);
61 impl BinkAudioDecoder {
62 fn new(use_dct: bool) -> Self {
63 let mut quants: [f32; 96] = [0.0; 96];
64 for i in 0..quants.len() {
65 quants[i] = ((i as f32) * 0.0664 / consts::LOG10_E).exp();
68 ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, 0),
69 chmap: NAChannelMap::new(),
71 transform: Transform::None,
75 bands: [MAX_BANDS + 1; 26],
79 delay: [[0.0; 256]; 2],
84 fn decode_block(&mut self, br: &mut BitReader) -> DecoderResult<()> {
86 let flt = br.read(32)?;
87 self.coeffs[0] = f32::from_bits(flt) * self.scale;
88 let flt = br.read(32)?;
89 self.coeffs[1] = f32::from_bits(flt) * self.scale;
91 self.coeffs[0] = read_bink_float(br)? * self.scale;
92 self.coeffs[1] = read_bink_float(br)? * self.scale;
94 let mut quants: [f32; MAX_BANDS] = [0.0; MAX_BANDS];
95 for i in 0..self.num_bands {
96 let idx = br.read(8)? as usize;
97 quants[i] = self.quants[idx.min(self.quants.len() - 1)] * self.scale;
100 let mut band_idx = 0;
101 self.coeffs = [0.0; 4096];
102 while idx < self.len {
103 let width = if self.version_b {
107 let idx = br.read(4)? as usize;
113 let end = (idx + width).min(self.len);
114 let bits = br.read(4)? as u8;
117 while self.bands[band_idx] <= i { band_idx += 1; }
118 let q = quants[band_idx - 1];
119 let coeff = br.read(bits)?;
122 self.coeffs[i] = -(coeff as f32) * q;
124 self.coeffs[i] = (coeff as f32) * q;
133 #[allow(clippy::transmute_ptr_to_ptr)]
134 fn output(&mut self, dst: &mut [f32], off0: usize, off1: usize, chno: usize) {
135 match self.transform {
136 Transform::DCT(ref mut dct) => {
137 dct.do_dct_inplace(&mut self.coeffs[0..]);
139 Transform::RDFT(ref mut rdft) => {
141 let buf = &mut self.coeffs[0..];
142 rdft.do_rdft_inplace(std::mem::transmute::<&mut [f32], &mut [FFTComplex]>(buf));
147 if self.use_dct || self.chmap.num_channels() == 1 {
148 let overlap_len = if self.first_frm { 0 } else { self.len >> 4 };
149 let out = if chno == 0 { &mut dst[off0..] } else { &mut dst[off1..] };
150 overlap(&self.delay[chno], &self.coeffs, out, overlap_len, 1);
151 let out2 = &mut out[overlap_len..self.duration];
152 out2.copy_from_slice(&self.coeffs[overlap_len..self.duration]);
153 for i in 0..(self.len >> 4) {
154 self.delay[chno][i] = self.coeffs[self.duration + i];
157 let overlap_len = if self.first_frm { 0 } else { self.len >> 8 };
158 overlap(&self.delay[0], &self.coeffs[0..], &mut dst[off0..], overlap_len, 2);
159 overlap(&self.delay[1], &self.coeffs[1..], &mut dst[off1..], overlap_len, 2);
160 for i in overlap_len..self.duration {
161 dst[i + off0] = self.coeffs[i * 2 + 0];
162 dst[i + off1] = self.coeffs[i * 2 + 1];
164 for i in 0..(self.len >> 8) {
165 self.delay[0][i] = self.coeffs[self.duration * 2 + i * 2 + 0];
166 self.delay[1][i] = self.coeffs[self.duration * 2 + i * 2 + 1];
172 const CRITICAL_FREQS: [usize; MAX_BANDS] = [
173 100, 200, 300, 400, 510, 630, 770, 920,
174 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150,
175 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500,
179 const RUN_TAB: [usize; 16] = [ 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 ];
181 impl NADecoder for BinkAudioDecoder {
182 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
183 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
184 let srate = ainfo.get_sample_rate();
185 let channels = ainfo.get_channels();
186 validate!(channels <= 2);
187 self.ainfo = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, 2);
188 self.chmap = NAChannelMap::from_str(if channels == 2 {"L,R"} else {"C"}).unwrap();
189 if let Some(ref edata) = info.get_extradata() {
190 if edata.as_slice() == b"BIKb" {
191 self.version_b = true;
194 self.version_b = false;
196 let mut frame_bits = if srate < 22050 { 9 } else if srate < 44100 { 10 } else { 11 };
197 if !self.use_dct && !self.version_b {
200 self.len = 1 << frame_bits;
201 self.duration = self.len - (self.len >> 4);
202 let single = !self.use_dct && channels == 2; // RDFT codes samples interleaved as single buffer
206 self.transform = if !self.use_dct {
207 Transform::RDFT(RDFTBuilder::new_rdft(self.len >> 1, false, false))
209 Transform::DCT(DCT::new(DCTMode::DCT_III, self.len))
211 self.scale = if !self.use_dct {
212 1.0 / (32768.0 * (self.len as f32).sqrt())
214 (2.0 / (self.len as f32)).sqrt() / 1024.0
216 let s_srate = if single { srate } else { srate >> 1 } as usize;
218 while self.num_bands < CRITICAL_FREQS.len() && CRITICAL_FREQS[self.num_bands - 1] < s_srate {
222 for i in 1..self.num_bands {
223 self.bands[i] = (CRITICAL_FREQS[i - 1] * self.len / s_srate) & !1;
225 self.bands[self.num_bands] = self.len;
226 self.first_frm = true;
230 Err(DecoderError::InvalidData)
233 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
234 let info = pkt.get_stream().get_info();
235 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
236 let pktbuf = pkt.get_buffer();
237 validate!(pktbuf.len() > 1);
238 let mut br = BitReader::new(&pktbuf, BitReaderMode::LE);
239 let nsamples = br.read(32)? as usize;
240 // validate!(nsamples % self.duration == 0);
242 let abuf = alloc_audio_buffer(self.ainfo, nsamples / self.chmap.num_channels() / 2, self.chmap.clone())?;
243 let mut adata = abuf.get_abuf_f32().unwrap();
244 let mut off0 = adata.get_offset(0);
245 let mut off1 = adata.get_offset(1);
246 let dst = adata.get_data_mut().unwrap();
248 let num_subframes = nsamples / self.duration / self.chmap.num_channels() / 2;
250 for _subfrm in 0..num_subframes {
254 self.decode_block(&mut br)?;
255 self.output(&mut dst[0..], off0, off1, 0);
256 if self.chmap.num_channels() > 1 && self.use_dct {
257 self.decode_block(&mut br)?;
258 self.output(&mut dst[0..], off0, off1, 1);
260 self.first_frm = false;
261 let left = br.left() & 31;
263 br.skip(left as u32)?;
265 off0 += self.duration;
266 off1 += self.duration;
269 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
270 frm.set_duration(Some(self.duration as u64));
271 frm.set_keyframe(false);
274 Err(DecoderError::InvalidData)
277 fn flush(&mut self) {
278 self.delay = [[0.0; 256]; 2];
282 impl NAOptionHandler for BinkAudioDecoder {
283 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
284 fn set_options(&mut self, _options: &[NAOption]) { }
285 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
288 pub fn get_decoder_dct() -> Box<dyn NADecoder + Send> {
289 Box::new(BinkAudioDecoder::new(true))
292 pub fn get_decoder_rdft() -> Box<dyn NADecoder + Send> {
293 Box::new(BinkAudioDecoder::new(false))
298 use nihav_core::codecs::RegisteredDecoders;
299 use nihav_core::demuxers::RegisteredDemuxers;
300 use nihav_codec_support::test::dec_video::*;
301 use crate::rad_register_all_decoders;
302 use crate::rad_register_all_demuxers;
305 fn test_bink_audio_dct() {
306 let mut dmx_reg = RegisteredDemuxers::new();
307 rad_register_all_demuxers(&mut dmx_reg);
308 let mut dec_reg = RegisteredDecoders::new();
309 rad_register_all_decoders(&mut dec_reg);
311 // sample: https://samples.mplayerhq.hu/game-formats/bink/ActivisionLogo.bik
312 let file = "assets/RAD/ActivisionLogo.bik";
313 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
316 fn test_bink_audio_rdft() {
317 let mut dmx_reg = RegisteredDemuxers::new();
318 rad_register_all_demuxers(&mut dmx_reg);
319 let mut dec_reg = RegisteredDecoders::new();
320 rad_register_all_decoders(&mut dec_reg);
322 // sample from Heroes of Might and Magic 3
323 let file = "assets/RAD/NWCLOGO.BIK";
324 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);