1use anyhow::{bail, Context, Result};
12use std::fs::File;
13use std::io::{Cursor, Read, Seek, SeekFrom};
14use std::path::Path;
15
16#[derive(Debug, Clone)]
17pub struct NwaHeader {
18 pub channels: u16,
19 pub bits_per_sample: u16,
20 pub samples_per_sec: u32,
21 pub pack_mod: i32,
22 pub zero_mod: i32,
23 pub unit_cnt: u32,
24 pub original_size: u32,
25 pub pack_size: u32,
26 pub sample_cnt: u32,
27 pub unit_sample_cnt: u32,
28 pub last_sample_cnt: u32,
29 pub last_sample_pack_size: u32,
30}
31
32impl NwaHeader {
33 pub fn is_uncompressed(&self) -> bool {
34 self.pack_mod == -1
35 }
36
37 pub fn frame_count(&self) -> u32 {
38 if self.channels == 0 {
39 return 0;
40 }
41 self.sample_cnt / (self.channels as u32)
42 }
43}
44
45#[derive(Debug)]
46struct UnitCache {
47 unit_no: i32,
48 unit_sample_cnt: u32,
49 buf: Vec<u8>,
50}
51
52impl UnitCache {
53 fn new() -> Self {
54 Self {
55 unit_no: -1,
56 unit_sample_cnt: 0,
57 buf: Vec::new(),
58 }
59 }
60}
61
62trait ReadSeek: Read + Seek {}
63impl<T: Read + Seek> ReadSeek for T {}
64
65pub struct NwaReader {
67 file: Box<dyn ReadSeek>,
68 base_offset: u64,
69 header: NwaHeader,
70 unit_offsets: Vec<u32>,
71 one_sample_byte_size: u32,
72 read_sample_pos: u32,
73 cache: UnitCache,
74}
75
76
77impl std::fmt::Debug for NwaReader {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 f.debug_struct("NwaReader")
80 .field("base_offset", &self.base_offset)
81 .field("header", &self.header)
82 .field("unit_offsets_len", &self.unit_offsets.len())
83 .field("one_sample_byte_size", &self.one_sample_byte_size)
84 .field("read_sample_pos", &self.read_sample_pos)
85 .finish()
86 }
87}
88
89impl NwaReader {
90 pub fn open(path: impl AsRef<Path>) -> Result<Self> {
91 Self::open_with_offset(path, 0)
92 }
93
94 pub fn open_with_offset(path: impl AsRef<Path>, base_offset: u64) -> Result<Self> {
95 let mut file =
96 File::open(&path).with_context(|| format!("open NWA: {}", path.as_ref().display()))?;
97 if base_offset != 0 {
98 file.seek(SeekFrom::Start(base_offset))?;
99 }
100 let header = read_header(&mut file)?;
101
102 let mut unit_offsets = Vec::new();
103 if header.pack_mod != -1 {
104 unit_offsets.resize(header.unit_cnt as usize, 0);
105 let mut tmp = vec![0u8; header.unit_cnt as usize * 4];
106 file.read_exact(&mut tmp)?;
107 for i in 0..header.unit_cnt as usize {
108 let o = u32::from_le_bytes([
109 tmp[i * 4],
110 tmp[i * 4 + 1],
111 tmp[i * 4 + 2],
112 tmp[i * 4 + 3],
113 ]);
114 unit_offsets[i] = o;
115 }
116 }
117
118 let one_sample_byte_size = (header.bits_per_sample as u32) / 8;
119
120 Ok(Self {
121 file: Box::new(file),
122 base_offset,
123 header,
124 unit_offsets,
125 one_sample_byte_size,
126 read_sample_pos: 0,
127 cache: UnitCache::new(),
128 })
129 }
130
131 pub fn open_from_bytes(bytes: Vec<u8>) -> Result<Self> {
132 let mut file = Cursor::new(bytes);
133 let header = read_header_from_reader(&mut file)?;
134
135 let mut unit_offsets = Vec::new();
136 if header.pack_mod != -1 {
137 unit_offsets.resize(header.unit_cnt as usize, 0);
138 let mut tmp = vec![0u8; header.unit_cnt as usize * 4];
139 file.read_exact(&mut tmp)?;
140 for i in 0..header.unit_cnt as usize {
141 let o = u32::from_le_bytes([
142 tmp[i * 4],
143 tmp[i * 4 + 1],
144 tmp[i * 4 + 2],
145 tmp[i * 4 + 3],
146 ]);
147 unit_offsets[i] = o;
148 }
149 }
150
151 let one_sample_byte_size = (header.bits_per_sample as u32) / 8;
152
153 Ok(Self {
154 file: Box::new(file),
155 base_offset: 0,
156 header,
157 unit_offsets,
158 one_sample_byte_size,
159 read_sample_pos: 0,
160 cache: UnitCache::new(),
161 })
162 }
163
164 pub fn header(&self) -> &NwaHeader {
165 &self.header
166 }
167
168 pub fn set_read_sample_pos(&mut self, frame_pos: u32) {
170 self.read_sample_pos = frame_pos.saturating_mul(self.header.channels as u32);
171 }
172
173 pub fn get_read_sample_pos(&self) -> u32 {
175 let ch = self.header.channels as u32;
176 if ch == 0 {
177 0
178 } else {
179 self.read_sample_pos / ch
180 }
181 }
182
183 pub fn read_samples(&mut self, frame_cnt: u32) -> Result<Vec<u8>> {
187 if self.header.channels != 1 && self.header.channels != 2 {
188 bail!("unsupported channels: {}", self.header.channels);
189 }
190 if self.header.bits_per_sample != 8 && self.header.bits_per_sample != 16 {
191 bail!(
192 "unsupported bits_per_sample: {}",
193 self.header.bits_per_sample
194 );
195 }
196
197 let need_byte_size =
198 (frame_cnt as u64) * (self.header.channels as u64) * (self.one_sample_byte_size as u64);
199 let mut out = vec![0u8; need_byte_size as usize];
200 let mut dp = 0usize;
201 let mut need = need_byte_size as i64;
202
203 while need > 0 {
204 if self.read_sample_pos >= self.header.sample_cnt {
205 break;
206 }
207
208 let copy_byte_size: usize;
209 if self.header.pack_mod == -1 {
210 copy_byte_size = self.read_no_pack_data(need as u64, &mut out[dp..])?;
212 } else {
213 let unit_no = (self.read_sample_pos / self.header.unit_sample_cnt) as u32;
215 self.read_unit(unit_no)?;
216
217 let ofs = ((self.read_sample_pos % self.header.unit_sample_cnt) as usize)
218 * (self.one_sample_byte_size as usize);
219 let mut cb = (self.cache.unit_sample_cnt as usize
220 * self.one_sample_byte_size as usize)
221 .saturating_sub(ofs);
222 if cb > need as usize {
223 cb = need as usize;
224 }
225 if cb == 0 {
226 break;
227 }
228 out[dp..dp + cb].copy_from_slice(&self.cache.buf[ofs..ofs + cb]);
229 copy_byte_size = cb;
230 }
231
232 if copy_byte_size == 0 {
233 break;
234 }
235 dp += copy_byte_size;
236 need -= copy_byte_size as i64;
237 self.read_sample_pos += (copy_byte_size as u32) / self.one_sample_byte_size;
238 }
239
240 out.truncate(dp);
241 Ok(out)
242 }
243
244 pub fn to_wav_bytes(&mut self) -> Result<Vec<u8>> {
246 let total_frames = self.header.frame_count();
247 self.set_read_sample_pos(0);
248 let pcm = self.read_samples(total_frames)?;
249
250 let fmt_tag: u16 = 1; let channels = self.header.channels;
252 let sample_rate = self.header.samples_per_sec;
253 let bits = self.header.bits_per_sample;
254 let block_align = (channels as u32 * (bits as u32 / 8)) as u16;
255 let byte_rate = sample_rate * (block_align as u32);
256 let data_len = pcm.len() as u32;
257
258 let mut wav = Vec::with_capacity(44 + pcm.len());
259 wav.extend_from_slice(b"RIFF");
260 wav.extend_from_slice(&(36u32 + data_len).to_le_bytes());
261 wav.extend_from_slice(b"WAVE");
262
263 wav.extend_from_slice(b"fmt ");
264 wav.extend_from_slice(&16u32.to_le_bytes());
265 wav.extend_from_slice(&fmt_tag.to_le_bytes());
266 wav.extend_from_slice(&channels.to_le_bytes());
267 wav.extend_from_slice(&sample_rate.to_le_bytes());
268 wav.extend_from_slice(&byte_rate.to_le_bytes());
269 wav.extend_from_slice(&block_align.to_le_bytes());
270 wav.extend_from_slice(&bits.to_le_bytes());
271
272 wav.extend_from_slice(b"data");
273 wav.extend_from_slice(&data_len.to_le_bytes());
274 wav.extend_from_slice(&pcm);
275 Ok(wav)
276 }
277
278 fn read_no_pack_data(&mut self, need_byte_size: u64, out: &mut [u8]) -> Result<usize> {
279 let data_ofs = (self.read_sample_pos as u64) * (self.one_sample_byte_size as u64);
280 let file_ofs = self.base_offset + 44 + data_ofs; self.file.seek(SeekFrom::Start(file_ofs))?;
283
284 let max_data_len = (self.header.sample_cnt as u64) * (self.one_sample_byte_size as u64);
286 let remain = max_data_len.saturating_sub(data_ofs);
287 let to_read = std::cmp::min(need_byte_size, std::cmp::min(remain, out.len() as u64));
288 let mut buf = &mut out[..to_read as usize];
289 self.file.read_exact(&mut buf)?;
290 Ok(to_read as usize)
291 }
292
293 fn read_unit(&mut self, unit_no: u32) -> Result<()> {
294 if self.cache.unit_no == unit_no as i32 {
295 return Ok(());
296 }
297
298 if unit_no >= self.header.unit_cnt {
299 bail!(
300 "unit_no out of range: {} >= {}",
301 unit_no,
302 self.header.unit_cnt
303 );
304 }
305
306 if self.header.pack_mod == -1 {
307 bail!("read_unit called for uncompressed NWA");
308 }
309 if self.header.bits_per_sample != 16 {
310 bail!(
311 "compressed NWA currently requires 16-bit PCM (got {})",
312 self.header.bits_per_sample
313 );
314 }
315
316 let (unit_sample_cnt, src_size) = if unit_no == self.header.unit_cnt - 1 {
317 (
318 self.header.last_sample_cnt,
319 self.header.last_sample_pack_size,
320 )
321 } else {
322 let a = self.unit_offsets[unit_no as usize] as u64;
323 let b = self.unit_offsets[unit_no as usize + 1] as u64;
324 (self.header.unit_sample_cnt, (b.saturating_sub(a)) as u32)
325 };
326
327 let src_ofs = self.base_offset + (self.unit_offsets[unit_no as usize] as u64);
328 self.file.seek(SeekFrom::Start(src_ofs))?;
329 let mut src = vec![0u8; src_size as usize];
330 self.file.read_exact(&mut src)?;
331
332 self.cache.buf.resize(unit_sample_cnt as usize * 2, 0);
333 nwa_unpack_unit(
334 &src,
335 self.header.pack_mod,
336 self.header.zero_mod != 0,
337 unit_sample_cnt,
338 &mut self.cache.buf,
339 )?;
340
341 self.cache.unit_no = unit_no as i32;
342 self.cache.unit_sample_cnt = unit_sample_cnt;
343 Ok(())
344 }
345}
346
347fn read_header(file: &mut File) -> Result<NwaHeader> {
348 read_header_from_reader(file)
349}
350
351fn read_header_from_reader<R: Read + ?Sized>(file: &mut R) -> Result<NwaHeader> {
352 let mut buf = [0u8; 44];
353 file.read_exact(&mut buf)?;
354 let mut o = 0usize;
355
356 let channels = u16::from_le_bytes([buf[o], buf[o + 1]]);
357 o += 2;
358 let bits_per_sample = u16::from_le_bytes([buf[o], buf[o + 1]]);
359 o += 2;
360 let samples_per_sec = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
361 o += 4;
362 let pack_mod = i32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
363 o += 4;
364 let zero_mod = i32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
365 o += 4;
366 let unit_cnt = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
367 o += 4;
368 let original_size = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
369 o += 4;
370 let pack_size = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
371 o += 4;
372 let sample_cnt = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
373 o += 4;
374 let unit_sample_cnt = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
375 o += 4;
376 let last_sample_cnt = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
377 o += 4;
378 let last_sample_pack_size = u32::from_le_bytes([buf[o], buf[o + 1], buf[o + 2], buf[o + 3]]);
379
380 Ok(NwaHeader {
381 channels,
382 bits_per_sample,
383 samples_per_sec,
384 pack_mod,
385 zero_mod,
386 unit_cnt,
387 original_size,
388 pack_size,
389 sample_cnt,
390 unit_sample_cnt,
391 last_sample_cnt,
392 last_sample_pack_size,
393 })
394}
395
396struct BitReaderLE<'a> {
397 buf: &'a [u8],
398 byte_pos: usize,
399 bit_pos: u8,
400}
401
402impl<'a> BitReaderLE<'a> {
403 fn new(buf: &'a [u8]) -> Self {
404 Self {
405 buf,
406 byte_pos: 0,
407 bit_pos: 0,
408 }
409 }
410
411 fn read_bits(&mut self, n: u8) -> u32 {
412 debug_assert!(n <= 8);
413 let b0 = *self.buf.get(self.byte_pos).unwrap_or(&0);
414 let b1 = *self.buf.get(self.byte_pos + 1).unwrap_or(&0);
415 let w = u16::from_le_bytes([b0, b1]);
416 let v = ((w as u32) >> (self.bit_pos as u32)) & ((1u32 << n) - 1);
417
418 self.bit_pos = self.bit_pos.wrapping_add(n);
419 if self.bit_pos >= 8 {
420 self.byte_pos += (self.bit_pos / 8) as usize;
421 self.bit_pos &= 7;
422 }
423 v
424 }
425}
426
427fn nwa_unpack_unit(
428 src: &[u8],
429 pack_mod: i32,
430 zero_mod: bool,
431 src_smp_cnt: u32,
432 dst_le_i16: &mut [u8],
433) -> Result<()> {
434 if dst_le_i16.len() < src_smp_cnt as usize * 2 {
435 bail!("dst buffer too small");
436 }
437
438 let mut br = BitReaderLE::new(src);
439 let mut now_l: i32 = 0;
440 let mut now_r: i32 = 0;
441 let mut zero_cnt: u32 = 0;
442
443 let mut mod_map = pack_mod;
444 match mod_map {
445 0 => mod_map = 2,
446 1 => mod_map = 1,
447 2 => mod_map = 0,
448 _ => {}
449 }
450
451 match mod_map {
452 0 => unpack16(
453 &mut br,
454 zero_mod,
455 src_smp_cnt,
456 dst_le_i16,
457 3,
458 &mut now_l,
459 &mut now_r,
460 &mut zero_cnt,
461 ),
462 1 => unpack16(
463 &mut br,
464 zero_mod,
465 src_smp_cnt,
466 dst_le_i16,
467 4,
468 &mut now_l,
469 &mut now_r,
470 &mut zero_cnt,
471 ),
472 2 => unpack16(
473 &mut br,
474 zero_mod,
475 src_smp_cnt,
476 dst_le_i16,
477 5,
478 &mut now_l,
479 &mut now_r,
480 &mut zero_cnt,
481 ),
482 3 => unpack16(
483 &mut br,
484 zero_mod,
485 src_smp_cnt,
486 dst_le_i16,
487 6,
488 &mut now_l,
489 &mut now_r,
490 &mut zero_cnt,
491 ),
492 4 => unpack16(
493 &mut br,
494 zero_mod,
495 src_smp_cnt,
496 dst_le_i16,
497 7,
498 &mut now_l,
499 &mut now_r,
500 &mut zero_cnt,
501 ),
502 5 => unpack16(
503 &mut br,
504 zero_mod,
505 src_smp_cnt,
506 dst_le_i16,
507 8,
508 &mut now_l,
509 &mut now_r,
510 &mut zero_cnt,
511 ),
512 _ => bail!("invalid pack_mod: {}", pack_mod),
513 }
514}
515
516fn get_zero_count(br: &mut BitReaderLE) -> u32 {
517 let mut zero_cnt = br.read_bits(1);
518 if zero_cnt == 1 {
519 zero_cnt = br.read_bits(2);
520 if zero_cnt == 3 {
521 zero_cnt = br.read_bits(8);
522 }
523 }
524 zero_cnt as u32
525}
526
527fn apply_delta(br: &mut BitReaderLE, mod_n: u8, data_n: u8, nowsmp: &mut i32) {
528 let (bits, sign_mask, shift): (u8, u32, u8) = match (mod_n, data_n) {
529 (3, 1) => (3, 0x04, 5),
530 (3, 2) => (3, 0x04, 6),
531 (3, 3) => (3, 0x04, 7),
532 (3, 4) => (3, 0x04, 8),
533 (3, 5) => (3, 0x04, 9),
534 (3, 6) => (3, 0x04, 10),
535 (3, 7) => (6, 0x20, 11),
536
537 (4, 1) => (4, 0x08, 4),
538 (4, 2) => (4, 0x08, 5),
539 (4, 3) => (4, 0x08, 6),
540 (4, 4) => (4, 0x08, 7),
541 (4, 5) => (4, 0x08, 8),
542 (4, 6) => (4, 0x08, 9),
543 (4, 7) => (7, 0x40, 10),
544
545 (5, 1) => (5, 0x10, 3),
546 (5, 2) => (5, 0x10, 4),
547 (5, 3) => (5, 0x10, 5),
548 (5, 4) => (5, 0x10, 6),
549 (5, 5) => (5, 0x10, 7),
550 (5, 6) => (5, 0x10, 8),
551 (5, 7) => (8, 0x80, 9),
552
553 (6, 1) => (6, 0x20, 2),
554 (6, 2) => (6, 0x20, 3),
555 (6, 3) => (6, 0x20, 4),
556 (6, 4) => (6, 0x20, 5),
557 (6, 5) => (6, 0x20, 6),
558 (6, 6) => (6, 0x20, 7),
559 (6, 7) => (8, 0x80, 9),
560
561 (7, 1) => (7, 0x40, 2),
562 (7, 2) => (7, 0x40, 3),
563 (7, 3) => (7, 0x40, 4),
564 (7, 4) => (7, 0x40, 5),
565 (7, 5) => (7, 0x40, 6),
566 (7, 6) => (7, 0x40, 7),
567 (7, 7) => (8, 0x80, 9),
568
569 (8, 1) => (8, 0x80, 2),
570 (8, 2) => (8, 0x80, 3),
571 (8, 3) => (8, 0x80, 4),
572 (8, 4) => (8, 0x80, 5),
573 (8, 5) => (8, 0x80, 6),
574 (8, 6) => (8, 0x80, 7),
575 (8, 7) => (8, 0x80, 9),
576 _ => return,
577 };
578
579 let mut dat_code = br.read_bits(bits);
580 if (dat_code & sign_mask) != 0 {
581 dat_code &= !sign_mask;
582 *nowsmp -= ((dat_code as i32) << shift);
583 } else {
584 *nowsmp += ((dat_code as i32) << shift);
585 }
586}
587
588fn unpack16(
589 br: &mut BitReaderLE,
590 zero_mod: bool,
591 src_smp_cnt: u32,
592 dst_le_i16: &mut [u8],
593 mod_n: u8,
594 now_l: &mut i32,
595 now_r: &mut i32,
596 zero_cnt: &mut u32,
597) -> Result<()> {
598 for i in 0..src_smp_cnt {
599 let nowsmp_ref: &mut i32 = if (i & 1) == 0 { now_l } else { now_r };
600
601 if *zero_cnt != 0 {
602 *zero_cnt -= 1;
603 } else {
604 let mod_code = br.read_bits(3) as u8;
605 match mod_code {
606 0 => {
607 if zero_mod {
608 *zero_cnt = get_zero_count(br);
609 }
610 }
611 1 => apply_delta(br, mod_n, 1, nowsmp_ref),
612 2 => apply_delta(br, mod_n, 2, nowsmp_ref),
613 3 => apply_delta(br, mod_n, 3, nowsmp_ref),
614 4 => apply_delta(br, mod_n, 4, nowsmp_ref),
615 5 => apply_delta(br, mod_n, 5, nowsmp_ref),
616 6 => apply_delta(br, mod_n, 6, nowsmp_ref),
617 7 => {
618 let b = br.read_bits(1);
619 if b == 0 {
620 apply_delta(br, mod_n, 7, nowsmp_ref);
621 } else {
622 *nowsmp_ref = 0;
623 }
624 }
625 _ => {}
626 }
627 }
628
629 let s = (*nowsmp_ref as i16).to_le_bytes();
631 let o = (i as usize) * 2;
632 dst_le_i16[o] = s[0];
633 dst_le_i16[o + 1] = s[1];
634 }
635 Ok(())
636}