]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::codecs::*; | |
2 | use nihav_core::dsp::dct::*; | |
3 | use nihav_core::dsp::fft::*; | |
4 | use nihav_core::io::bitreader::*; | |
5 | use std::f32::consts; | |
6 | use std::str::FromStr; | |
7 | ||
8 | enum Transform { | |
9 | None, | |
10 | DCT(DCT), | |
11 | RDFT(RDFT), | |
12 | } | |
13 | ||
14 | const MAX_BANDS: usize = 25; | |
15 | ||
16 | struct BinkAudioDecoder { | |
17 | ainfo: NAAudioInfo, | |
18 | chmap: NAChannelMap, | |
19 | use_dct: bool, | |
20 | version_b: bool, | |
21 | transform: Transform, | |
22 | len: usize, | |
23 | quants: [f32; 96], | |
24 | bands: [usize; MAX_BANDS + 1], | |
25 | num_bands: usize, | |
26 | duration: usize, | |
27 | coeffs: [f32; 4096], | |
28 | delay: [[f32; 256]; 2], | |
29 | first_frm: bool, | |
30 | scale: f32, | |
31 | } | |
32 | ||
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()?; | |
37 | let v = if exp >= 0 { | |
38 | (mant as f32) * ((1 << exp) as f32) | |
39 | } else { | |
40 | (mant as f32) / ((1 << -exp) as f32) | |
41 | }; | |
42 | if sign { | |
43 | Ok(-v) | |
44 | } else { | |
45 | Ok(v) | |
46 | }*/ | |
47 | let exp = br.read(5)? as u8; | |
48 | let mant = br.read(23)? as u32; | |
49 | let sign = br.read(1)? as u32; | |
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)) | |
53 | } | |
54 | ||
55 | fn overlap(a: &[f32], b: &[f32], dst: &mut [f32], len: usize, step: usize) { | |
56 | for i in 0..len { | |
57 | dst[i] = (a[i] * ((len - i) as f32) + b[i * step] * (i as f32)) / (len as f32); | |
58 | } | |
59 | } | |
60 | ||
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(); | |
66 | } | |
67 | Self { | |
68 | ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, 0), | |
69 | chmap: NAChannelMap::new(), | |
70 | use_dct, | |
71 | transform: Transform::None, | |
72 | version_b: false, | |
73 | len: 0, | |
74 | quants: quants, | |
75 | bands: [MAX_BANDS + 1; 26], | |
76 | num_bands: 0, | |
77 | duration: 0, | |
78 | coeffs: [0.0; 4096], | |
79 | delay: [[0.0; 256]; 2], | |
80 | first_frm: true, | |
81 | scale: 1.0, | |
82 | } | |
83 | } | |
84 | fn decode_block(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
85 | if self.version_b { | |
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; | |
90 | } else { | |
91 | self.coeffs[0] = read_bink_float(br)? * self.scale; | |
92 | self.coeffs[1] = read_bink_float(br)? * self.scale; | |
93 | } | |
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; | |
98 | } | |
99 | let mut idx = 2; | |
100 | let mut band_idx = 0; | |
101 | self.coeffs = [0.0; 4096]; | |
102 | while idx < self.len { | |
103 | let width = if self.version_b { | |
104 | 16 | |
105 | } else { | |
106 | if br.read_bool()? { | |
107 | let idx = br.read(4)? as usize; | |
108 | RUN_TAB[idx] * 8 | |
109 | } else { | |
110 | 8 | |
111 | } | |
112 | }; | |
113 | let end = (idx + width).min(self.len); | |
114 | let bits = br.read(4)? as u8; | |
115 | if bits != 0 { | |
116 | for i in idx..end { | |
117 | while self.bands[band_idx] <= i { band_idx += 1; } | |
118 | let q = quants[band_idx - 1]; | |
119 | let coeff = br.read(bits)?; | |
120 | if coeff != 0 { | |
121 | if br.read_bool()? { | |
122 | self.coeffs[i] = -(coeff as f32) * q; | |
123 | } else { | |
124 | self.coeffs[i] = (coeff as f32) * q; | |
125 | } | |
126 | } | |
127 | } | |
128 | } | |
129 | idx = end; | |
130 | } | |
131 | Ok(()) | |
132 | } | |
133 | fn output(&mut self, dst: &mut [f32], off0: usize, off1: usize, chno: usize) { | |
134 | match self.transform { | |
135 | Transform::DCT(ref mut dct) => { | |
136 | dct.do_dct_inplace(&mut self.coeffs[0..]); | |
137 | }, | |
138 | Transform::RDFT(ref mut rdft) => { | |
139 | unsafe { | |
140 | let buf = &mut self.coeffs[0..]; | |
141 | rdft.do_rdft_inplace(std::mem::transmute::<&mut [f32], &mut [FFTComplex]>(buf)); | |
142 | } | |
143 | }, | |
144 | _ => unreachable!(), | |
145 | }; | |
146 | if self.use_dct || self.chmap.num_channels() == 1 { | |
147 | let overlap_len = if self.first_frm { 0 } else { self.len >> 4 }; | |
148 | let out = if chno == 0 { &mut dst[off0..] } else { &mut dst[off1..] }; | |
149 | overlap(&self.delay[chno], &self.coeffs, out, overlap_len, 1); | |
150 | let out2 = &mut out[overlap_len..self.duration]; | |
151 | out2.copy_from_slice(&self.coeffs[overlap_len..self.duration]); | |
152 | for i in 0..(self.len >> 4) { | |
153 | self.delay[chno][i] = self.coeffs[self.duration + i]; | |
154 | } | |
155 | } else { | |
156 | let overlap_len = if self.first_frm { 0 } else { self.len >> 8 }; | |
157 | overlap(&self.delay[0], &self.coeffs[0..], &mut dst[off0..], overlap_len, 2); | |
158 | overlap(&self.delay[1], &self.coeffs[1..], &mut dst[off1..], overlap_len, 2); | |
159 | for i in overlap_len..self.duration { | |
160 | dst[i + off0] = self.coeffs[i * 2 + 0]; | |
161 | dst[i + off1] = self.coeffs[i * 2 + 1]; | |
162 | } | |
163 | for i in 0..(self.len >> 8) { | |
164 | self.delay[0][i] = self.coeffs[self.duration * 2 + i * 2 + 0]; | |
165 | self.delay[1][i] = self.coeffs[self.duration * 2 + i * 2 + 1]; | |
166 | } | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | const CRITICAL_FREQS: [usize; MAX_BANDS] = [ | |
172 | 100, 200, 300, 400, 510, 630, 770, 920, | |
173 | 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, | |
174 | 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, | |
175 | 24500 | |
176 | ]; | |
177 | ||
178 | const RUN_TAB: [usize; 16] = [ 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 ]; | |
179 | ||
180 | impl NADecoder for BinkAudioDecoder { | |
181 | fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> { | |
182 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
183 | let srate = ainfo.get_sample_rate(); | |
184 | let channels = ainfo.get_channels(); | |
185 | validate!(channels <= 2); | |
186 | self.ainfo = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, 2); | |
187 | self.chmap = NAChannelMap::from_str(if channels == 2 {"L,R"} else {"C"}).unwrap(); | |
188 | if let Some(ref edata) = info.get_extradata() { | |
189 | if edata.as_slice() == b"BIKb" { | |
190 | self.version_b = true; | |
191 | } | |
192 | } else { | |
193 | self.version_b = false; | |
194 | } | |
195 | let mut frame_bits = if srate < 22050 { 9 } else if srate < 44100 { 10 } else { 11 }; | |
196 | if !self.use_dct && !self.version_b { | |
197 | frame_bits += 1; | |
198 | } | |
199 | self.len = 1 << frame_bits; | |
200 | self.duration = self.len - (self.len >> 4); | |
201 | let single = !self.use_dct && channels == 2; // RDFT codes samples interleaved as single buffer | |
202 | if single { | |
203 | self.duration >>= 1; | |
204 | } | |
205 | self.transform = if !self.use_dct { | |
206 | Transform::RDFT(RDFTBuilder::new_rdft(FFTMode::SplitRadix, self.len >> 1, false, false)) | |
207 | } else { | |
208 | Transform::DCT(DCT::new(DCTMode::DCT_III, self.len)) | |
209 | }; | |
210 | self.scale = if !self.use_dct { | |
211 | 1.0 / (32768.0 * (self.len as f32).sqrt()) | |
212 | } else { | |
213 | (2.0 / (self.len as f32)).sqrt() / 1024.0 | |
214 | }; | |
215 | let s_srate = if single { srate } else { srate >> 1 } as usize; | |
216 | self.num_bands = 1; | |
217 | while self.num_bands < CRITICAL_FREQS.len() && CRITICAL_FREQS[self.num_bands - 1] < s_srate { | |
218 | self.num_bands += 1; | |
219 | } | |
220 | self.bands[0] = 2; | |
221 | for i in 1..self.num_bands { | |
222 | self.bands[i] = (CRITICAL_FREQS[i - 1] * self.len / s_srate) & !1; | |
223 | } | |
224 | self.bands[self.num_bands] = self.len; | |
225 | self.first_frm = true; | |
226 | ||
227 | Ok(()) | |
228 | } else { | |
229 | Err(DecoderError::InvalidData) | |
230 | } | |
231 | } | |
232 | fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
233 | let info = pkt.get_stream().get_info(); | |
234 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { | |
235 | let pktbuf = pkt.get_buffer(); | |
236 | validate!(pktbuf.len() > 1); | |
237 | let mut br = BitReader::new(&pktbuf, pktbuf.len(), BitReaderMode::LE); | |
238 | let nsamples = br.read(32)? as usize; | |
239 | // validate!(nsamples % self.duration == 0); | |
240 | ||
241 | let abuf = alloc_audio_buffer(self.ainfo, nsamples / self.chmap.num_channels() / 2, self.chmap.clone())?; | |
242 | let mut adata = abuf.get_abuf_f32().unwrap(); | |
243 | let mut off0 = adata.get_offset(0); | |
244 | let mut off1 = adata.get_offset(1); | |
245 | let dst = adata.get_data_mut().unwrap(); | |
246 | ||
247 | let num_subframes = nsamples / self.duration / self.chmap.num_channels() / 2; | |
248 | ||
249 | for _subfrm in 0..num_subframes { | |
250 | if self.use_dct { | |
251 | br.skip(2)?; | |
252 | } | |
253 | self.decode_block(&mut br)?; | |
254 | self.output(&mut dst[0..], off0, off1, 0); | |
255 | if self.chmap.num_channels() > 1 && self.use_dct { | |
256 | self.decode_block(&mut br)?; | |
257 | self.output(&mut dst[0..], off0, off1, 1); | |
258 | } | |
259 | self.first_frm = false; | |
260 | let left = br.left() & 31; | |
261 | if left != 0 { | |
262 | br.skip(left as u32)?; | |
263 | } | |
264 | off0 += self.duration; | |
265 | off1 += self.duration; | |
266 | } | |
267 | ||
268 | let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); | |
269 | frm.set_duration(Some(self.duration as u64)); | |
270 | frm.set_keyframe(false); | |
271 | Ok(Rc::new(RefCell::new(frm))) | |
272 | } else { | |
273 | Err(DecoderError::InvalidData) | |
274 | } | |
275 | } | |
276 | } | |
277 | ||
278 | pub fn get_decoder_dct() -> Box<NADecoder> { | |
279 | Box::new(BinkAudioDecoder::new(true)) | |
280 | } | |
281 | ||
282 | pub fn get_decoder_rdft() -> Box<NADecoder> { | |
283 | Box::new(BinkAudioDecoder::new(false)) | |
284 | } | |
285 | ||
286 | #[cfg(test)] | |
287 | mod test { | |
288 | use nihav_core::codecs::RegisteredDecoders; | |
289 | use nihav_core::demuxers::RegisteredDemuxers; | |
290 | use nihav_core::test::dec_video::*; | |
291 | use crate::codecs::rad_register_all_codecs; | |
292 | use crate::demuxers::rad_register_all_demuxers; | |
293 | ||
294 | #[test] | |
295 | fn test_bink_audio() { | |
296 | let mut dmx_reg = RegisteredDemuxers::new(); | |
297 | rad_register_all_demuxers(&mut dmx_reg); | |
298 | let mut dec_reg = RegisteredDecoders::new(); | |
299 | rad_register_all_codecs(&mut dec_reg); | |
300 | ||
301 | // let file = "assets/RAD/ActivisionLogo.bik"; | |
302 | let file = "assets/RAD/original.bik"; | |
303 | // let file = "assets/RAD/Snd0a110c51.dee"; | |
304 | // let file = "assets/RAD/NEW.BIK"; | |
305 | // let file = "assets/RAD/ge_video_86l.bk2"; | |
306 | test_decode_audio("bink", file, None, "bink", &dmx_reg, &dec_reg); | |
307 | } | |
308 | } |