binkaud: split out common data definitions for the future encoder
[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];
90 for i in 0..self.num_bands {
91 let idx = br.read(8)? as usize;
92 quants[i] = self.quants[idx.min(self.quants.len() - 1)] * self.scale;
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
100 } else {
101 if br.read_bool()? {
102 let idx = br.read(4)? as usize;
103 RUN_TAB[idx] * 8
104 } else {
105 8
106 }
107 };
108 let end = (idx + width).min(self.len);
109 let bits = br.read(4)? as u8;
110 if bits != 0 {
111 for i in idx..end {
112 while self.bands[band_idx] <= i { band_idx += 1; }
113 let q = quants[band_idx - 1];
114 let coeff = br.read(bits)?;
115 if coeff != 0 {
116 if br.read_bool()? {
117 self.coeffs[i] = -(coeff as f32) * q;
118 } else {
119 self.coeffs[i] = (coeff as f32) * q;
120 }
121 }
122 }
123 }
124 idx = end;
125 }
126 Ok(())
127 }
bf109afe 128 #[allow(clippy::transmute_ptr_to_ptr)]
e5ea6525
KS
129 fn output(&mut self, dst: &mut [f32], off0: usize, off1: usize, chno: usize) {
130 match self.transform {
131 Transform::DCT(ref mut dct) => {
132 dct.do_dct_inplace(&mut self.coeffs[0..]);
133 },
134 Transform::RDFT(ref mut rdft) => {
135 unsafe {
136 let buf = &mut self.coeffs[0..];
137 rdft.do_rdft_inplace(std::mem::transmute::<&mut [f32], &mut [FFTComplex]>(buf));
138 }
139 },
140 _ => unreachable!(),
141 };
142 if self.use_dct || self.chmap.num_channels() == 1 {
143 let overlap_len = if self.first_frm { 0 } else { self.len >> 4 };
144 let out = if chno == 0 { &mut dst[off0..] } else { &mut dst[off1..] };
145 overlap(&self.delay[chno], &self.coeffs, out, overlap_len, 1);
146 let out2 = &mut out[overlap_len..self.duration];
147 out2.copy_from_slice(&self.coeffs[overlap_len..self.duration]);
148 for i in 0..(self.len >> 4) {
149 self.delay[chno][i] = self.coeffs[self.duration + i];
150 }
b3799375 151 } else {
e5ea6525
KS
152 let overlap_len = if self.first_frm { 0 } else { self.len >> 8 };
153 overlap(&self.delay[0], &self.coeffs[0..], &mut dst[off0..], overlap_len, 2);
154 overlap(&self.delay[1], &self.coeffs[1..], &mut dst[off1..], overlap_len, 2);
155 for i in overlap_len..self.duration {
156 dst[i + off0] = self.coeffs[i * 2 + 0];
157 dst[i + off1] = self.coeffs[i * 2 + 1];
158 }
159 for i in 0..(self.len >> 8) {
160 self.delay[0][i] = self.coeffs[self.duration * 2 + i * 2 + 0];
161 self.delay[1][i] = self.coeffs[self.duration * 2 + i * 2 + 1];
162 }
163 }
164 }
165}
166
e5ea6525 167impl NADecoder for BinkAudioDecoder {
01613464 168 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
e5ea6525
KS
169 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
170 let srate = ainfo.get_sample_rate();
171 let channels = ainfo.get_channels();
172 validate!(channels <= 2);
173 self.ainfo = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, 2);
ef1d2014 174 self.chmap = NAChannelMap::from_str(if channels == 2 {"L,R"} else {"C"}).unwrap();
e5ea6525
KS
175 if let Some(ref edata) = info.get_extradata() {
176 if edata.as_slice() == b"BIKb" {
177 self.version_b = true;
178 }
179 } else {
180 self.version_b = false;
181 }
182 let mut frame_bits = if srate < 22050 { 9 } else if srate < 44100 { 10 } else { 11 };
183 if !self.use_dct && !self.version_b {
184 frame_bits += 1;
185 }
186 self.len = 1 << frame_bits;
187 self.duration = self.len - (self.len >> 4);
188 let single = !self.use_dct && channels == 2; // RDFT codes samples interleaved as single buffer
189 if single {
190 self.duration >>= 1;
191 }
192 self.transform = if !self.use_dct {
9e78289c 193 Transform::RDFT(RDFTBuilder::new_rdft(self.len >> 1, false, false))
e5ea6525
KS
194 } else {
195 Transform::DCT(DCT::new(DCTMode::DCT_III, self.len))
196 };
197 self.scale = if !self.use_dct {
198 1.0 / (32768.0 * (self.len as f32).sqrt())
199 } else {
200 (2.0 / (self.len as f32)).sqrt() / 1024.0
201 };
202 let s_srate = if single { srate } else { srate >> 1 } as usize;
e9f61dd2 203 init_bands(s_srate, self.len, &mut self.num_bands, &mut self.bands);
e5ea6525
KS
204 self.first_frm = true;
205
206 Ok(())
207 } else {
208 Err(DecoderError::InvalidData)
209 }
210 }
01613464 211 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
e5ea6525
KS
212 let info = pkt.get_stream().get_info();
213 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
214 let pktbuf = pkt.get_buffer();
215 validate!(pktbuf.len() > 1);
fa90ccfb 216 let mut br = BitReader::new(&pktbuf, BitReaderMode::LE);
e5ea6525
KS
217 let nsamples = br.read(32)? as usize;
218// validate!(nsamples % self.duration == 0);
219
b70cc006 220 let abuf = alloc_audio_buffer(self.ainfo, nsamples / self.chmap.num_channels() / 2, self.chmap.clone())?;
e5ea6525
KS
221 let mut adata = abuf.get_abuf_f32().unwrap();
222 let mut off0 = adata.get_offset(0);
223 let mut off1 = adata.get_offset(1);
1a967e6b 224 let dst = adata.get_data_mut().unwrap();
e5ea6525
KS
225
226 let num_subframes = nsamples / self.duration / self.chmap.num_channels() / 2;
227
228 for _subfrm in 0..num_subframes {
229 if self.use_dct {
230 br.skip(2)?;
231 }
232 self.decode_block(&mut br)?;
233 self.output(&mut dst[0..], off0, off1, 0);
234 if self.chmap.num_channels() > 1 && self.use_dct {
235 self.decode_block(&mut br)?;
236 self.output(&mut dst[0..], off0, off1, 1);
237 }
238 self.first_frm = false;
239 let left = br.left() & 31;
240 if left != 0 {
241 br.skip(left as u32)?;
242 }
243 off0 += self.duration;
244 off1 += self.duration;
245 }
246
247 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
248 frm.set_duration(Some(self.duration as u64));
249 frm.set_keyframe(false);
171860fc 250 Ok(frm.into_ref())
e5ea6525
KS
251 } else {
252 Err(DecoderError::InvalidData)
253 }
254 }
f9be4e75
KS
255 fn flush(&mut self) {
256 self.delay = [[0.0; 256]; 2];
257 }
e5ea6525 258}
606c448e 259
7d57ae2f
KS
260impl NAOptionHandler for BinkAudioDecoder {
261 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
262 fn set_options(&mut self, _options: &[NAOption]) { }
263 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
264}
265
08a1fab7 266pub fn get_decoder_dct() -> Box<dyn NADecoder + Send> {
e5ea6525 267 Box::new(BinkAudioDecoder::new(true))
606c448e
KS
268}
269
08a1fab7 270pub fn get_decoder_rdft() -> Box<dyn NADecoder + Send> {
e5ea6525
KS
271 Box::new(BinkAudioDecoder::new(false))
272}
273
274#[cfg(test)]
275mod test {
276 use nihav_core::codecs::RegisteredDecoders;
277 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 278 use nihav_codec_support::test::dec_video::*;
78fb6560 279 use crate::rad_register_all_decoders;
e64739f8 280 use crate::rad_register_all_demuxers;
e5ea6525
KS
281
282 #[test]
3b981842 283 fn test_bink_audio_dct() {
e5ea6525
KS
284 let mut dmx_reg = RegisteredDemuxers::new();
285 rad_register_all_demuxers(&mut dmx_reg);
286 let mut dec_reg = RegisteredDecoders::new();
78fb6560 287 rad_register_all_decoders(&mut dec_reg);
e5ea6525 288
886cde48 289 // sample: https://samples.mplayerhq.hu/game-formats/bink/ActivisionLogo.bik
3b981842
KS
290 let file = "assets/RAD/ActivisionLogo.bik";
291 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
292 }
293 #[test]
294 fn test_bink_audio_rdft() {
295 let mut dmx_reg = RegisteredDemuxers::new();
296 rad_register_all_demuxers(&mut dmx_reg);
297 let mut dec_reg = RegisteredDecoders::new();
78fb6560 298 rad_register_all_decoders(&mut dec_reg);
3b981842 299
886cde48 300 // sample from Heroes of Might and Magic 3
3b981842 301 let file = "assets/RAD/NWCLOGO.BIK";
5580b11b 302 test_decode_audio("bink", file, None, None/*Some("bink")*/, &dmx_reg, &dec_reg);
e5ea6525 303 }
606c448e 304}