]> git.nihav.org Git - nihav.git/blame - nihav-rad/src/codecs/binkaud.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-rad / src / codecs / binkaud.rs
CommitLineData
606c448e 1use nihav_core::codecs::*;
b4d5b851
KS
2use nihav_codec_support::dsp::dct::*;
3use nihav_codec_support::dsp::fft::*;
e5ea6525 4use nihav_core::io::bitreader::*;
e5ea6525
KS
5use std::str::FromStr;
6
e9f61dd2
KS
7use super::binkauddata::*;
8
e5ea6525
KS
9enum Transform {
10 None,
11 DCT(DCT),
12 RDFT(RDFT),
13}
14
e5ea6525
KS
15struct BinkAudioDecoder {
16 ainfo: NAAudioInfo,
17 chmap: NAChannelMap,
18 use_dct: bool,
19 version_b: bool,
20 transform: Transform,
21 len: usize,
22 quants: [f32; 96],
23 bands: [usize; MAX_BANDS + 1],
24 num_bands: usize,
25 duration: usize,
26 coeffs: [f32; 4096],
27 delay: [[f32; 256]; 2],
28 first_frm: bool,
29 scale: f32,
30}
31
32fn read_bink_float(br: &mut BitReader) -> DecoderResult<f32> {
33 /*let exp = (br.read(5)? as i8) - 23;
34 let mant = br.read(23)? as u32;
35 let sign = br.read_bool()?;
36 let v = if exp >= 0 {
37 (mant as f32) * ((1 << exp) as f32)
38 } else {
39 (mant as f32) / ((1 << -exp) as f32)
40 };
41 if sign {
42 Ok(-v)
43 } else {
44 Ok(v)
45 }*/
46 let exp = br.read(5)? as u8;
e6aaad5c
KS
47 let mant = br.read(23)?;
48 let sign = br.read(1)?;
e5ea6525
KS
49 let nexp = exp.wrapping_add(0x7E) as u32;
50 let nmant = (mant << 1) & ((1 << 23) - 1);
51 Ok(f32::from_bits((sign << 31) | (nexp << 23) | nmant))
52}
53
54fn overlap(a: &[f32], b: &[f32], dst: &mut [f32], len: usize, step: usize) {
55 for i in 0..len {
56 dst[i] = (a[i] * ((len - i) as f32) + b[i * step] * (i as f32)) / (len as f32);
57 }
58}
59
60impl BinkAudioDecoder {
61 fn new(use_dct: bool) -> Self {
e5ea6525
KS
62 Self {
63 ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, 0),
64 chmap: NAChannelMap::new(),
65 use_dct,
66 transform: Transform::None,
67 version_b: false,
68 len: 0,
e9f61dd2 69 quants: get_quants_table(),
e5ea6525
KS
70 bands: [MAX_BANDS + 1; 26],
71 num_bands: 0,
72 duration: 0,
73 coeffs: [0.0; 4096],
74 delay: [[0.0; 256]; 2],
75 first_frm: true,
76 scale: 1.0,
77 }
78 }
79 fn decode_block(&mut self, br: &mut BitReader) -> DecoderResult<()> {
80 if self.version_b {
81 let flt = br.read(32)?;
82 self.coeffs[0] = f32::from_bits(flt) * self.scale;
83 let flt = br.read(32)?;
84 self.coeffs[1] = f32::from_bits(flt) * self.scale;
85 } else {
86 self.coeffs[0] = read_bink_float(br)? * self.scale;
87 self.coeffs[1] = read_bink_float(br)? * self.scale;
88 }
89 let mut quants: [f32; MAX_BANDS] = [0.0; MAX_BANDS];
3687b8b3 90 for quant in quants[..self.num_bands].iter_mut() {
e5ea6525 91 let idx = br.read(8)? as usize;
3687b8b3 92 *quant = self.quants[idx.min(self.quants.len() - 1)] * self.scale;
e5ea6525
KS
93 }
94 let mut idx = 2;
95 let mut band_idx = 0;
96 self.coeffs = [0.0; 4096];
97 while idx < self.len {
98 let width = if self.version_b {
99 16
3687b8b3
KS
100 } else if br.read_bool()? {
101 let idx = br.read(4)? as usize;
102 RUN_TAB[idx] * 8
e5ea6525 103 } else {
3687b8b3 104 8
e5ea6525
KS
105 };
106 let end = (idx + width).min(self.len);
107 let bits = br.read(4)? as u8;
108 if bits != 0 {
109 for i in idx..end {
110 while self.bands[band_idx] <= i { band_idx += 1; }
111 let q = quants[band_idx - 1];
112 let coeff = br.read(bits)?;
113 if coeff != 0 {
114 if br.read_bool()? {
115 self.coeffs[i] = -(coeff as f32) * q;
116 } else {
117 self.coeffs[i] = (coeff as f32) * q;
118 }
119 }
120 }
121 }
122 idx = end;
123 }
124 Ok(())
125 }
3687b8b3 126 #[allow(clippy::identity_op)]
bf109afe 127 #[allow(clippy::transmute_ptr_to_ptr)]
e5ea6525
KS
128 fn output(&mut self, dst: &mut [f32], off0: usize, off1: usize, chno: usize) {
129 match self.transform {
130 Transform::DCT(ref mut dct) => {
131 dct.do_dct_inplace(&mut self.coeffs[0..]);
132 },
133 Transform::RDFT(ref mut rdft) => {
134 unsafe {
135 let buf = &mut self.coeffs[0..];
136 rdft.do_rdft_inplace(std::mem::transmute::<&mut [f32], &mut [FFTComplex]>(buf));
137 }
47da4a32
KS
138 for i in (0..self.coeffs.len()).step_by(2) {
139 self.coeffs.swap(i, i + 1);
140 }
e5ea6525
KS
141 },
142 _ => unreachable!(),
143 };
144 if self.use_dct || self.chmap.num_channels() == 1 {
145 let overlap_len = if self.first_frm { 0 } else { self.len >> 4 };
146 let out = if chno == 0 { &mut dst[off0..] } else { &mut dst[off1..] };
147 overlap(&self.delay[chno], &self.coeffs, out, overlap_len, 1);
148 let out2 = &mut out[overlap_len..self.duration];
149 out2.copy_from_slice(&self.coeffs[overlap_len..self.duration]);
150 for i in 0..(self.len >> 4) {
151 self.delay[chno][i] = self.coeffs[self.duration + i];
152 }
b3799375 153 } else {
e5ea6525
KS
154 let overlap_len = if self.first_frm { 0 } else { self.len >> 8 };
155 overlap(&self.delay[0], &self.coeffs[0..], &mut dst[off0..], overlap_len, 2);
156 overlap(&self.delay[1], &self.coeffs[1..], &mut dst[off1..], overlap_len, 2);
157 for i in overlap_len..self.duration {
158 dst[i + off0] = self.coeffs[i * 2 + 0];
159 dst[i + off1] = self.coeffs[i * 2 + 1];
160 }
161 for i in 0..(self.len >> 8) {
162 self.delay[0][i] = self.coeffs[self.duration * 2 + i * 2 + 0];
163 self.delay[1][i] = self.coeffs[self.duration * 2 + i * 2 + 1];
164 }
165 }
166 }
167}
168
e5ea6525 169impl NADecoder for BinkAudioDecoder {
01613464 170 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
e5ea6525
KS
171 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
172 let srate = ainfo.get_sample_rate();
173 let channels = ainfo.get_channels();
174 validate!(channels <= 2);
175 self.ainfo = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, 2);
ef1d2014 176 self.chmap = NAChannelMap::from_str(if channels == 2 {"L,R"} else {"C"}).unwrap();
e5ea6525
KS
177 if let Some(ref edata) = info.get_extradata() {
178 if edata.as_slice() == b"BIKb" {
179 self.version_b = true;
180 }
181 } else {
182 self.version_b = false;
183 }
184 let mut frame_bits = if srate < 22050 { 9 } else if srate < 44100 { 10 } else { 11 };
d3ebda9b 185 if !self.use_dct && !self.version_b && channels > 1 {
e5ea6525
KS
186 frame_bits += 1;
187 }
188 self.len = 1 << frame_bits;
189 self.duration = self.len - (self.len >> 4);
190 let single = !self.use_dct && channels == 2; // RDFT codes samples interleaved as single buffer
191 if single {
192 self.duration >>= 1;
193 }
194 self.transform = if !self.use_dct {
9e78289c 195 Transform::RDFT(RDFTBuilder::new_rdft(self.len >> 1, false, false))
e5ea6525
KS
196 } else {
197 Transform::DCT(DCT::new(DCTMode::DCT_III, self.len))
198 };
199 self.scale = if !self.use_dct {
200 1.0 / (32768.0 * (self.len as f32).sqrt())
201 } else {
202 (2.0 / (self.len as f32)).sqrt() / 1024.0
203 };
204 let s_srate = if single { srate } else { srate >> 1 } as usize;
e9f61dd2 205 init_bands(s_srate, self.len, &mut self.num_bands, &mut self.bands);
e5ea6525
KS
206 self.first_frm = true;
207
208 Ok(())
209 } else {
210 Err(DecoderError::InvalidData)
211 }
212 }
01613464 213 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
e5ea6525
KS
214 let info = pkt.get_stream().get_info();
215 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
216 let pktbuf = pkt.get_buffer();
217 validate!(pktbuf.len() > 1);
fa90ccfb 218 let mut br = BitReader::new(&pktbuf, BitReaderMode::LE);
e5ea6525
KS
219 let nsamples = br.read(32)? as usize;
220// validate!(nsamples % self.duration == 0);
221
b70cc006 222 let abuf = alloc_audio_buffer(self.ainfo, nsamples / self.chmap.num_channels() / 2, self.chmap.clone())?;
e5ea6525
KS
223 let mut adata = abuf.get_abuf_f32().unwrap();
224 let mut off0 = adata.get_offset(0);
225 let mut off1 = adata.get_offset(1);
1a967e6b 226 let dst = adata.get_data_mut().unwrap();
e5ea6525
KS
227
228 let num_subframes = nsamples / self.duration / self.chmap.num_channels() / 2;
229
230 for _subfrm in 0..num_subframes {
231 if self.use_dct {
232 br.skip(2)?;
233 }
234 self.decode_block(&mut br)?;
235 self.output(&mut dst[0..], off0, off1, 0);
236 if self.chmap.num_channels() > 1 && self.use_dct {
237 self.decode_block(&mut br)?;
238 self.output(&mut dst[0..], off0, off1, 1);
239 }
240 self.first_frm = false;
241 let left = br.left() & 31;
242 if left != 0 {
243 br.skip(left as u32)?;
244 }
245 off0 += self.duration;
246 off1 += self.duration;
247 }
248
249 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
250 frm.set_duration(Some(self.duration as u64));
251 frm.set_keyframe(false);
171860fc 252 Ok(frm.into_ref())
e5ea6525
KS
253 } else {
254 Err(DecoderError::InvalidData)
255 }
256 }
f9be4e75
KS
257 fn flush(&mut self) {
258 self.delay = [[0.0; 256]; 2];
259 }
e5ea6525 260}
606c448e 261
7d57ae2f
KS
262impl NAOptionHandler for BinkAudioDecoder {
263 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
264 fn set_options(&mut self, _options: &[NAOption]) { }
265 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
266}
267
08a1fab7 268pub fn get_decoder_dct() -> Box<dyn NADecoder + Send> {
e5ea6525 269 Box::new(BinkAudioDecoder::new(true))
606c448e
KS
270}
271
08a1fab7 272pub fn get_decoder_rdft() -> Box<dyn NADecoder + Send> {
e5ea6525
KS
273 Box::new(BinkAudioDecoder::new(false))
274}
275
276#[cfg(test)]
277mod test {
278 use nihav_core::codecs::RegisteredDecoders;
279 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 280 use nihav_codec_support::test::dec_video::*;
78fb6560 281 use crate::rad_register_all_decoders;
e64739f8 282 use crate::rad_register_all_demuxers;
e5ea6525
KS
283
284 #[test]
3b981842 285 fn test_bink_audio_dct() {
e5ea6525
KS
286 let mut dmx_reg = RegisteredDemuxers::new();
287 rad_register_all_demuxers(&mut dmx_reg);
288 let mut dec_reg = RegisteredDecoders::new();
78fb6560 289 rad_register_all_decoders(&mut dec_reg);
e5ea6525 290
886cde48 291 // sample: https://samples.mplayerhq.hu/game-formats/bink/ActivisionLogo.bik
3b981842
KS
292 let file = "assets/RAD/ActivisionLogo.bik";
293 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
294 }
295 #[test]
d3ebda9b
KS
296 fn test_bink_audio_rdft_mono() {
297 let mut dmx_reg = RegisteredDemuxers::new();
298 rad_register_all_demuxers(&mut dmx_reg);
299 let mut dec_reg = RegisteredDecoders::new();
300 rad_register_all_decoders(&mut dec_reg);
301
302 // sample from Star Trek: Armada demo
303 let file = "assets/RAD/F1DEM1.bik";
304 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
305 }
306 #[test]
307 fn test_bink_audio_rdft_stereo() {
3b981842
KS
308 let mut dmx_reg = RegisteredDemuxers::new();
309 rad_register_all_demuxers(&mut dmx_reg);
310 let mut dec_reg = RegisteredDecoders::new();
78fb6560 311 rad_register_all_decoders(&mut dec_reg);
3b981842 312
886cde48 313 // sample from Heroes of Might and Magic 3
3b981842 314 let file = "assets/RAD/NWCLOGO.BIK";
5580b11b 315 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
e5ea6525 316 }
606c448e 317}