vmd: add IMA ADPCM audio support
[nihav.git] / nihav-game / src / codecs / vmd.rs
CommitLineData
9895bd7b
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
b4d5b851 3use nihav_codec_support::codecs::HAMShuffler;
979faef7 4use nihav_codec_support::codecs::imaadpcm::*;
9895bd7b 5use std::str::FromStr;
f45dfcf7 6use std::sync::Arc;
9895bd7b
KS
7
8macro_rules! lz_op {
9 (read; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $br:expr, $dst_size:expr) => {
10 validate!($dpos < $dst_size);
11 let b = $br.read_byte()?;
12 $dst[$dpos] = b;
13 $dpos += 1;
14 $window[$wpos] = b;
15 $wpos = ($wpos + 1) & 0xFFF;
16 };
17 (copy; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $off:expr, $dst_size:expr) => {
18 let b = $window[$off];
19 validate!($dpos < $dst_size);
20 $dst[$dpos] = b;
21 $dpos += 1;
22 $window[$wpos] = b;
23 $wpos = ($wpos + 1) & 0xFFF;
24 $off = ($off + 1) & 0xFFF;
25 };
26}
27fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
28 let mut window: [u8; 0x1000] = [0x20; 0x1000];
29
30 let dst_size = br.read_u32le()? as usize;
31 validate!(dst_size <= dst.len());
32 let mut pos;
33 let esc_len;
34 if br.peek_u32le()? == 0x56781234 {
35 br.read_skip(4)?;
36 pos = 0x111;
37 esc_len = 15;
38 } else {
39 pos = 0xFEE;
40 esc_len = 255;
41 }
42
43 let mut opos = 0;
44 while br.left() > 0 && opos < dst_size {
45 let op = br.read_byte()?;
46 if (op == 0xFF) && (br.left() > 8) {
47 for _ in 0..8 {
48 lz_op!(read; dst, opos, window, pos, br, dst_size);
49 }
50 } else {
51 for i in 0..8 {
52 if opos == dst_size { break; }
53 let is_literal = ((op >> i) & 1) != 0;
54 if is_literal {
55 lz_op!(read; dst, opos, window, pos, br, dst_size);
56 } else {
57 let b0 = br.read_byte()? as usize;
58 let b1 = br.read_byte()? as usize;
59 let mut off = b0 | ((b1 & 0xF0) << 4);
60 let mut len = b1 & 0xF;
61 if len == esc_len {
62 len = (br.read_byte()? as usize) + esc_len;
63 }
64 for _ in 0..len+3 {
65 lz_op!(copy; dst, opos, window, pos, off, dst_size);
66 }
67 }
68 }
69 }
70 }
71 Ok(())
72}
73
74fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
75 let end = br.tell() + (len as u64);
76 let mut dpos = 0;
77 if (len & 1) != 0 {
78 dst[dpos] = br.read_byte()?;
79 dpos += 1;
80 }
81 while dpos < dst.len() && br.tell() < end {
82 let val = br.read_byte()?;
83 let len = ((val & 0x7F) as usize) * 2;
84 validate!(dpos + len <= dst.len());
85 if (val & 0x80) != 0 {
86 let dst = &mut dst[dpos..][..len];
87 br.read_buf(dst)?;
88 } else {
771e522a
KS
89 let val1 = br.read_byte()?;
90 let val2 = br.read_byte()?;
91 for i in (0..len).step_by(2) {
92 dst[dpos + i] = val1;
93 dst[dpos + i + 1] = val2;
9895bd7b
KS
94 }
95 }
96 dpos += len;
97 }
98 Ok(())
99}
100
101fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
102 match method {
103 1 => {
104 for _ in 0..h {
105 let mut x = 0;
106 while x < w {
107 let val = br.read_byte()?;
108 let len = ((val & 0x7F) as usize) + 1;
109 validate!(x + len <= w);
110 if (val & 0x80) != 0 {
111 let pix = &mut dst[dpos + x..][..len];
112 br.read_buf(pix)?;
113 } // otherwise skip already existing data
114 x += len;
115 }
116 dpos += stride;
117 }
118 Ok(false)
119 },
120 2 => {
121 for _ in 0..h {
122 let pix = &mut dst[dpos..][..w];
123 br.read_buf(pix)?;
124 dpos += stride;
125 }
126 Ok(true)
127 },
128 3 => {
129 for _ in 0..h {
130 let mut x = 0;
131 while x < w {
132 let val = br.read_byte()?;
133 let len = ((val & 0x7F) as usize) + 1;
134 validate!(x + len <= w);
135 if (val & 0x80) != 0 {
136 let pix = &mut dst[dpos + x..][..len];
137 if br.peek_byte()? == 0xFF {
138 br.read_skip(1)?;
139 rle_unpack(br, len, pix)?;
140 } else {
141 br.read_buf(pix)?;
142 }
143 } // otherwise data is already there
144 x += len;
145 }
146 dpos += stride;
147 }
148 Ok(false)
149 },
e69b1148 150 _ => Err(DecoderError::InvalidData),
9895bd7b
KS
151 }
152}
153
154struct VMDVideoDecoder {
2422d969 155 info: NACodecInfoRef,
9895bd7b
KS
156 pal: [u8; 768],
157 buf: Vec<u8>,
158 width: usize,
159 height: usize,
73a1eecd
KS
160 xoff: usize,
161 yoff: usize,
9895bd7b
KS
162 hams: HAMShuffler,
163}
164
165impl VMDVideoDecoder {
166 fn new() -> Self {
167 Self {
2422d969 168 info: NACodecInfoRef::default(),
9895bd7b
KS
169 pal: [0; 768],
170 buf: Vec::new(),
171 width: 0,
172 height: 0,
73a1eecd
KS
173 xoff: 0,
174 yoff: 0,
9895bd7b
KS
175 hams: HAMShuffler::default(),
176 }
177 }
178 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
179 let paloff = buf.get_offset(1);
180 let stride = buf.get_stride(0);
1a967e6b 181 let data = buf.get_data_mut().unwrap();
9895bd7b
KS
182 let dst = data.as_mut_slice();
183
184 let frame_x = br.read_u16le()? as usize;
185 let frame_y = br.read_u16le()? as usize;
186 let frame_l = br.read_u16le()? as usize;
187 let frame_d = br.read_u16le()? as usize;
188 br.read_skip(1)?;
189 let flags = br.read_byte()?;
190 let has_pal = (flags & 0x02) != 0;
5961ae1d
KS
191 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
192 return Ok(false);
193 }
73a1eecd 194 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
9895bd7b 195 validate!(frame_l >= frame_x && frame_d >= frame_y);
73a1eecd 196 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
9895bd7b
KS
197
198 if has_pal {
199 br.read_skip(2)?;
200 for e in self.pal.iter_mut() {
201 let val = br.read_byte()?;
202 *e = (val << 2) | (val >> 4);
203 }
204 }
205
206 let dpal = &mut dst[paloff..][..768];
207 dpal.copy_from_slice(&self.pal[0..]);
208
209 if br.left() == 0 { return Ok(false); }
210
211 let w = frame_l + 1 - frame_x;
212 let h = frame_d + 1 - frame_y;
73a1eecd 213 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
9895bd7b
KS
214
215 let method = br.read_byte()?;
216 let is_intra;
217 if (method & 0x80) != 0 {
e69b1148 218 validate!(!self.buf.is_empty());
9895bd7b
KS
219 lz_unpack(br, &mut self.buf)?;
220 let mut mr = MemoryReader::new_read(&self.buf);
221 let mut buf_br = ByteReader::new(&mut mr);
222 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
223 } else {
224 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
225 }
226 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
227 }
228}
229
230impl NADecoder for VMDVideoDecoder {
01613464 231 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
232 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
233 self.width = vinfo.get_width();
234 self.height = vinfo.get_height();
235 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
2422d969 236 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
9895bd7b
KS
237 validate!(info.get_extradata().is_some());
238
239 if let Some(ref edata) = info.get_extradata() {
240 validate!(edata.len() == 0x330);
241 let unp_size = read_u32le(&edata[800..])? as usize;
ed6c9f8a 242 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
9895bd7b
KS
243 self.buf.resize(unp_size, 0);
244 for i in 0..768 {
245 let el = edata[28 + i];
246 self.pal[i] = (el << 2) | (el >> 4);
247 }
73a1eecd
KS
248 self.xoff = read_u16le(&edata[8..])? as usize;
249 self.yoff = read_u16le(&edata[10..])? as usize;
9895bd7b
KS
250 }
251
252 Ok(())
253 } else {
254 Err(DecoderError::InvalidData)
255 }
256 }
01613464 257 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
258 let src = pkt.get_buffer();
259 validate!(src.len() >= 10);
260
261 let mut mr = MemoryReader::new_read(&src);
262 let mut br = ByteReader::new(&mut mr);
263
264 let mut buf;
265 let bufret = self.hams.clone_ref();
266 if let Some(bbuf) = bufret {
267 buf = bbuf;
268 } else {
e69b1148 269 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
9895bd7b
KS
270 buf = bufinfo.get_vbuf().unwrap();
271 self.hams.add_frame(buf);
272 buf = self.hams.get_output_frame().unwrap();
273 }
274
275 let is_intra = self.decode_frame(&mut br, &mut buf)?;
276
277 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
278 frm.set_keyframe(is_intra);
279 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
171860fc 280 Ok(frm.into_ref())
9895bd7b 281 }
f9be4e75
KS
282 fn flush(&mut self) {
283 self.hams.clear();
284 }
9895bd7b
KS
285}
286
287
08a1fab7 288pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
289 Box::new(VMDVideoDecoder::new())
290}
291
f45dfcf7
KS
292#[derive(Clone,Copy,PartialEq)]
293enum VMDAudioMode {
294 U8,
295 DPCM,
296 StereoDPCM,
979faef7 297 ADPCM,
f45dfcf7
KS
298}
299
9895bd7b
KS
300struct VMDAudioDecoder {
301 ainfo: NAAudioInfo,
f45dfcf7 302 info: Arc<NACodecInfo>,
9895bd7b 303 chmap: NAChannelMap,
9895bd7b
KS
304 blk_align: usize,
305 blk_size: usize,
f45dfcf7
KS
306 mode: VMDAudioMode,
307 pred: [i32; 2],
308 last_byte: Option<u8>,
309 is_odd: bool,
310 ch: usize,
9895bd7b
KS
311}
312
313const SOL_AUD_STEPS16: [i16; 128] = [
314 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
315 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
316 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
317 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
318 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
319 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
320 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
321 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
322 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
323 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
324 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
325 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
326 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
327 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
328 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
329 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
330];
331
332impl VMDAudioDecoder {
333 fn new() -> Self {
334 Self {
335 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
f45dfcf7 336 info: NACodecInfo::new_dummy(),
9895bd7b 337 chmap: NAChannelMap::new(),
9895bd7b
KS
338 blk_align: 0,
339 blk_size: 0,
f45dfcf7
KS
340 mode: VMDAudioMode::U8,
341 pred: [0; 2],
342 last_byte: None,
343 is_odd: false,
344 ch: 0,
9895bd7b
KS
345 }
346 }
347 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
348 let channels = self.chmap.num_channels();
349 let mut off = [0, off1];
350 for _ in 0..nblocks {
351 if (mask & 1) != 0 {
352 for ch in 0..channels {
353 for i in 0..self.blk_align {
354 dst[off[ch] + i] = 0;
355 }
356 off[ch] += self.blk_align;
357 }
358 } else {
359 let mut pred: [i32; 2] = [0; 2];
360 for ch in 0..channels {
e69b1148 361 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
362 dst[off[ch]] = pred[ch] as i16;
363 off[ch] += 1;
364 }
365 let mut ch = 0;
366 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 367 for _ in channels..self.blk_align*channels {
f45dfcf7 368 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
9895bd7b
KS
369 //pred[ch] = pred[ch].max(-32768).min(32767);
370 dst[off[ch]] = pred[ch] as i16;
371 off[ch] += 1;
372 ch ^= flip_ch;
373 }
374 }
375 mask >>= 1;
376 }
377 validate!(br.left() == 0);
378 Ok(())
379 }
f45dfcf7
KS
380 fn pred16(pred: i32, val: u8) -> i32 {
381 if (val & 0x80) != 0 {
382 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
383 } else {
384 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
385 }
386 }
387 fn cvt_u8(val: u8) -> u8 {
6eda3136 388 val ^ 0x80
f45dfcf7 389 }
9895bd7b
KS
390}
391
392impl NADecoder for VMDAudioDecoder {
01613464 393 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
394 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
395 let fmt;
f45dfcf7
KS
396 let channels = ainfo.get_channels() as usize;
397 let edata = info.get_extradata();
398 let flags = if let Some(ref buf) = edata {
399 validate!(buf.len() >= 2);
400 (buf[0] as u16) | ((buf[1] as u16) << 8)
401 } else {
402 0
403 };
404 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
9895bd7b 405 if ainfo.get_format().get_bits() == 8 {
9895bd7b 406 self.blk_size = ainfo.get_block_len();
f45dfcf7
KS
407 self.blk_align = ainfo.get_block_len() / channels;
408 if (flags & 0x8000) == 0 {
409 fmt = SND_U8_FORMAT;
410 self.mode = VMDAudioMode::U8;
411 } else {
412 fmt = SND_S16_FORMAT;
413 self.mode = VMDAudioMode::StereoDPCM;
414 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
415 }
9895bd7b
KS
416 } else {
417 fmt = SND_S16P_FORMAT;
aa7e65d2 418 self.blk_align = ainfo.get_block_len();
979faef7
KS
419 if (flags & 0x10) == 0 {
420 self.blk_size = (ainfo.get_block_len() + 1) * channels;
421 self.mode = VMDAudioMode::DPCM;
422 } else {
423 self.blk_size = ainfo.get_block_len() / 2 + 3;
424 self.mode = VMDAudioMode::ADPCM;
425 }
9895bd7b 426 };
9895bd7b 427 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
f45dfcf7
KS
428 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
429 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
9895bd7b
KS
430 Ok(())
431 } else {
432 Err(DecoderError::InvalidData)
433 }
434 }
01613464 435 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
436 let info = pkt.get_stream().get_info();
437 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
438 let pktbuf = pkt.get_buffer();
439 validate!(pktbuf.len() >= 6);
440 let mut mr = MemoryReader::new_read(&pktbuf);
441 let mut br = ByteReader::new(&mut mr);
442 let blk_type = br.read_byte()?;
443 br.read_skip(9)?;
444 let mask;
445 let nblocks;
446 if blk_type == 2 { // initial
447 mask = br.read_u32le()?;
448 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
449 } else if blk_type == 3 { // silence
450 mask = 1;
451 nblocks = 1;
452 } else {
453 mask = 0;
454 nblocks = 1;
455 }
f45dfcf7
KS
456 let mut samples = nblocks * self.blk_align;
457 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
458 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
459 }
9895bd7b 460 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
f45dfcf7
KS
461 match self.mode {
462 VMDAudioMode::DPCM => {
463 let mut adata = abuf.get_abuf_i16().unwrap();
464 let off1 = adata.get_offset(1);
465 let mut dst = adata.get_data_mut().unwrap();
466 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
467 },
468 VMDAudioMode::U8 => {
469 let mut adata = abuf.get_abuf_u8().unwrap();
470 let dst = adata.get_data_mut().unwrap();
471 let mut doff = 0;
472 let mut mask = mask;
473 let channels = self.chmap.num_channels();
474 for _ in 0..nblocks {
475 if (mask & 1) != 0 {
476 for i in 0..self.blk_align * channels {
477 dst[doff + i] = 128;
478 }
479 } else if channels == 1 {
480 for i in 0..self.blk_size {
481 dst[doff + i] = br.read_byte()?;
482 }
483 } else {
484 for i in 0..self.blk_size {
485 let val = Self::cvt_u8(br.read_byte()?);
486 dst[doff + i] = val;
487 }
9895bd7b 488 }
f45dfcf7
KS
489 doff += self.blk_align * channels;
490 mask >>= 1;
491 }
492 },
493 VMDAudioMode::StereoDPCM => {
494 let mut adata = abuf.get_abuf_i16().unwrap();
495 let dst = adata.get_data_mut().unwrap();
496 let mut doff = 0;
497 let mut mask = mask;
498 let mut ch = self.ch;
499 for _ in 0..nblocks {
500 let put_sample = self.last_byte.is_some();
501 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
502 self.pred[ch] = Self::pred16(self.pred[ch], val);
503 dst[doff] = self.pred[ch] as i16;
504 doff += 1;
505 ch ^= 1;
506 self.last_byte = None;
9895bd7b 507 }
f45dfcf7
KS
508 if (mask & 1) != 0 {
509 for i in 0..self.blk_align {
510 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
511 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
512 }
513 if self.is_odd {
514 if put_sample {
515 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
516 doff += 1;
517 ch ^= 1;
518 } else {
519 self.last_byte = Some(0);
520 }
521 }
522 } else {
523 for i in 0..self.blk_align {
524 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
525 dst[doff + i * 2] = self.pred[ch] as i16;
526 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
527 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
528 }
529 if self.is_odd {
530 let val = br.read_byte()?;
531 if put_sample {
532 self.pred[ch] = Self::pred16(self.pred[ch], val);
533 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
534 doff += 1;
535 ch ^= 1;
536 } else {
537 self.last_byte = Some(val);
538 }
aa7e65d2
KS
539 }
540 }
f45dfcf7
KS
541 doff += self.blk_align * 2;
542 mask >>= 1;
9895bd7b 543 }
f45dfcf7
KS
544 self.ch = ch;
545 },
979faef7
KS
546 VMDAudioMode::ADPCM => {
547 let mut adata = abuf.get_abuf_i16().unwrap();
548 let dst = adata.get_data_mut().unwrap();
549 let mut doff = 0;
550 if self.chmap.num_channels() == 1 {
551 let mut mask = mask;
552 let mut ima = IMAState::new();
553 for _ in 0..nblocks {
554 if (mask & 1) != 0 {
555 doff += (self.blk_size - 3) * 2;
556 mask >>= 1;
557 continue;
558 }
559 let pred = br.read_u16le()? as i16;
560 let step = br.read_byte()?;
561 validate!((step as usize) < IMA_STEP_TABLE.len());
562 ima.reset(pred, step);
563 for _ in 3..self.blk_size {
564 let b = br.read_byte()?;
565 dst[doff] = ima.expand_sample(b >> 4);
566 doff += 1;
567 dst[doff] = ima.expand_sample(b & 0xF);
568 doff += 1;
569 }
570 mask >>= 1;
571 }
572 } else {
573 return Err(DecoderError::InvalidData);
574 }
575 },
f45dfcf7 576 };
9895bd7b 577
f45dfcf7 578 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
9895bd7b
KS
579 frm.set_duration(Some(samples as u64));
580 frm.set_keyframe(true);
171860fc 581 Ok(frm.into_ref())
9895bd7b
KS
582 } else {
583 Err(DecoderError::InvalidData)
584 }
585 }
f9be4e75
KS
586 fn flush(&mut self) {
587 }
9895bd7b
KS
588}
589
08a1fab7 590pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
591 Box::new(VMDAudioDecoder::new())
592}
593
594#[cfg(test)]
595mod test {
596 use nihav_core::codecs::RegisteredDecoders;
597 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 598 use nihav_codec_support::test::dec_video::*;
e64739f8
KS
599 use crate::game_register_all_codecs;
600 use crate::game_register_all_demuxers;
9895bd7b
KS
601 #[test]
602 fn test_vmd_video() {
603 let mut dmx_reg = RegisteredDemuxers::new();
604 game_register_all_demuxers(&mut dmx_reg);
605 let mut dec_reg = RegisteredDecoders::new();
606 game_register_all_codecs(&mut dec_reg);
607
fe435580
KS
608 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
609 ExpectedTestResult::MD5Frames(vec![
610 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
611 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
612 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
613 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
614 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
615 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
616 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
617 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
618 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
619 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
620 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
9895bd7b
KS
621 }
622 #[test]
fe435580 623 fn test_vmd_audio_u8() {
9895bd7b
KS
624 let mut dmx_reg = RegisteredDemuxers::new();
625 game_register_all_demuxers(&mut dmx_reg);
626 let mut dec_reg = RegisteredDecoders::new();
627 game_register_all_codecs(&mut dec_reg);
628
fe435580
KS
629 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
630 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
631 }
632 #[test]
633 fn test_vmd_audio_s16_old() {
634 let mut dmx_reg = RegisteredDemuxers::new();
635 game_register_all_demuxers(&mut dmx_reg);
636 let mut dec_reg = RegisteredDecoders::new();
637 game_register_all_codecs(&mut dec_reg);
638
639 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
640 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
641 }
642 #[test]
643 fn test_vmd_audio_s16_new() {
644 let mut dmx_reg = RegisteredDemuxers::new();
645 game_register_all_demuxers(&mut dmx_reg);
646 let mut dec_reg = RegisteredDecoders::new();
647 game_register_all_codecs(&mut dec_reg);
648
649 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
650 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
9895bd7b
KS
651 }
652}