]> git.nihav.org Git - nihav.git/blame - nihav-core/src/test/wavwriter.rs
allstuff: register duck crate
[nihav.git] / nihav-core / src / test / wavwriter.rs
CommitLineData
aca89041
KS
1use crate::io::byteio::*;
2use crate::frame::*;
cc0859d6
KS
3use std::io::SeekFrom;
4
5pub struct WavWriter<'a> {
6 io: &'a mut ByteWriter<'a>,
7 data_pos: u64,
8}
9
10fn write_byte(wr: &mut ByteWriter, sample: u8) -> ByteIOResult<()> {
11 wr.write_byte(sample)
12}
13
14fn write_s16(wr: &mut ByteWriter, sample: i16) -> ByteIOResult<()> {
15 wr.write_u16le(sample as u16)
16}
17
18fn write_s32(wr: &mut ByteWriter, sample: i32) -> ByteIOResult<()> {
19 wr.write_u16le((sample >> 16) as u16)
20}
21
22fn write_f32(wr: &mut ByteWriter, sample: f32) -> ByteIOResult<()> {
23 let mut out = (sample * 32768.0) as i32;
24 if out < -32768 { out = -32768; }
25 if out > 32767 { out = 32767; }
26 if out < 0 { out += 65536; }
27 wr.write_u16le(out as u16)
28}
29
30macro_rules! write_data {
31 ($wr:expr, $buf:expr, $write:ident) => ({
32 let len = $buf.get_length();
33 let ainfo = $buf.get_info();
34 let nch = ainfo.get_channels() as usize;
35 let mut offs: Vec<usize> = Vec::with_capacity(nch);
36 for ch in 0..nch { offs.push($buf.get_offset(ch)); }
37 let data = $buf.get_data();
38
39 for i in 0..len {
40 for ch in 0..nch {
41 let sample = data[offs[ch] + i];
42 $write($wr, sample)?;
43 }
44 }
45 })
46}
47
48impl<'a> WavWriter<'a> {
49 pub fn new(io: &'a mut ByteWriter<'a>) -> Self {
50 WavWriter { io: io, data_pos: 0 }
51 }
52 pub fn write_header(&mut self, ainfo: NAAudioInfo) -> ByteIOResult<()> {
53 let bits = ainfo.get_format().get_bits() as usize;
54
55 self.io.write_buf(b"RIFF")?;
56 self.io.write_u32le(0)?;
57 self.io.write_buf(b"WAVE")?;
58
59 self.io.write_buf(b"fmt ")?;
60 self.io.write_u32le(16)?;
61 self.io.write_u16le(0x0001)?; // PCM
62 self.io.write_u16le(ainfo.get_channels() as u16)?;
63 self.io.write_u32le(ainfo.get_sample_rate() as u32)?;
64
65 if bits < 16 {
66 self.io.write_u32le((ainfo.get_channels() as u32) * (ainfo.get_sample_rate() as u32))?;
67 self.io.write_u16le(ainfo.get_channels() as u16)?; // block align
68 self.io.write_u16le(8)?;
69 } else {
70 self.io.write_u32le(2 * (ainfo.get_channels() as u32) * (ainfo.get_sample_rate() as u32))?;
71 self.io.write_u16le((2 * ainfo.get_channels()) as u16)?; // block align
72 self.io.write_u16le(16)?;
73 }
74
75 self.io.write_buf(b"data")?;
76 self.io.write_u32le(0)?;
77
78 self.data_pos = self.io.tell();
79 Ok(())
80 }
81 pub fn write_frame(&mut self, abuf: NABufferType) -> ByteIOResult<()> {
82 match abuf {
83 NABufferType::AudioU8(ref buf) => {
84 write_data!(self.io, buf, write_byte);
85 }
86 NABufferType::AudioI16(ref buf) => {
87 write_data!(self.io, buf, write_s16);
88 }
89 NABufferType::AudioI32(ref buf) => {
90 write_data!(self.io, buf, write_s32);
91 }
92 NABufferType::AudioF32(ref buf) => {
93 write_data!(self.io, buf, write_f32);
94 }
95 NABufferType::AudioPacked(ref buf) => {
96 self.io.write_buf(buf.get_data().as_slice())?;
97 }
98 _ => {},
99 };
100 Ok(())
101 }
102}
103
104impl<'a> Drop for WavWriter<'a> {
105 #[allow(unused_variables)]
106 fn drop(&mut self) {
107 let size = self.io.tell();
108 if (self.data_pos > 0) && (size >= self.data_pos) {
109 let res = self.io.seek(SeekFrom::Start(4));
110 let res = self.io.write_u32le((size - 8) as u32);
111 let res = self.io.seek(SeekFrom::Start(self.data_pos - 4));
112 let res = self.io.write_u32le(((size as u64) - self.data_pos) as u32);
113 }
114 }
115}