From: Kostya Shishkov Date: Thu, 15 Jun 2017 12:32:54 +0000 (+0200) Subject: add wav output dumper for tests X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=cc0859d6dfd35bfb45b4303d26b4e0b979b3ba83;p=nihav.git add wav output dumper for tests --- diff --git a/src/lib.rs b/src/lib.rs index 90001d7..c0ae975 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,3 +11,6 @@ pub mod register; pub mod detect; pub mod dsp; + +#[cfg(test)] +mod test; diff --git a/src/test/mod.rs b/src/test/mod.rs new file mode 100644 index 0000000..a8fa2dc --- /dev/null +++ b/src/test/mod.rs @@ -0,0 +1 @@ +pub mod wavwriter; diff --git a/src/test/wavwriter.rs b/src/test/wavwriter.rs new file mode 100644 index 0000000..a68075e --- /dev/null +++ b/src/test/wavwriter.rs @@ -0,0 +1,115 @@ +use io::byteio::*; +use frame::*; +use std::io::SeekFrom; + +pub struct WavWriter<'a> { + io: &'a mut ByteWriter<'a>, + data_pos: u64, +} + +fn write_byte(wr: &mut ByteWriter, sample: u8) -> ByteIOResult<()> { + wr.write_byte(sample) +} + +fn write_s16(wr: &mut ByteWriter, sample: i16) -> ByteIOResult<()> { + wr.write_u16le(sample as u16) +} + +fn write_s32(wr: &mut ByteWriter, sample: i32) -> ByteIOResult<()> { + wr.write_u16le((sample >> 16) as u16) +} + +fn write_f32(wr: &mut ByteWriter, sample: f32) -> ByteIOResult<()> { + let mut out = (sample * 32768.0) as i32; + if out < -32768 { out = -32768; } + if out > 32767 { out = 32767; } + if out < 0 { out += 65536; } + wr.write_u16le(out as u16) +} + +macro_rules! write_data { + ($wr:expr, $buf:expr, $write:ident) => ({ + let len = $buf.get_length(); + let ainfo = $buf.get_info(); + let nch = ainfo.get_channels() as usize; + let mut offs: Vec = Vec::with_capacity(nch); + for ch in 0..nch { offs.push($buf.get_offset(ch)); } + let data = $buf.get_data(); + + for i in 0..len { + for ch in 0..nch { + let sample = data[offs[ch] + i]; + $write($wr, sample)?; + } + } + }) +} + +impl<'a> WavWriter<'a> { + pub fn new(io: &'a mut ByteWriter<'a>) -> Self { + WavWriter { io: io, data_pos: 0 } + } + pub fn write_header(&mut self, ainfo: NAAudioInfo) -> ByteIOResult<()> { + let bits = ainfo.get_format().get_bits() as usize; + + self.io.write_buf(b"RIFF")?; + self.io.write_u32le(0)?; + self.io.write_buf(b"WAVE")?; + + self.io.write_buf(b"fmt ")?; + self.io.write_u32le(16)?; + self.io.write_u16le(0x0001)?; // PCM + self.io.write_u16le(ainfo.get_channels() as u16)?; + self.io.write_u32le(ainfo.get_sample_rate() as u32)?; + + if bits < 16 { + self.io.write_u32le((ainfo.get_channels() as u32) * (ainfo.get_sample_rate() as u32))?; + self.io.write_u16le(ainfo.get_channels() as u16)?; // block align + self.io.write_u16le(8)?; + } else { + self.io.write_u32le(2 * (ainfo.get_channels() as u32) * (ainfo.get_sample_rate() as u32))?; + self.io.write_u16le((2 * ainfo.get_channels()) as u16)?; // block align + self.io.write_u16le(16)?; + } + + self.io.write_buf(b"data")?; + self.io.write_u32le(0)?; + + self.data_pos = self.io.tell(); + Ok(()) + } + pub fn write_frame(&mut self, abuf: NABufferType) -> ByteIOResult<()> { + match abuf { + NABufferType::AudioU8(ref buf) => { + write_data!(self.io, buf, write_byte); + } + NABufferType::AudioI16(ref buf) => { + write_data!(self.io, buf, write_s16); + } + NABufferType::AudioI32(ref buf) => { + write_data!(self.io, buf, write_s32); + } + NABufferType::AudioF32(ref buf) => { + write_data!(self.io, buf, write_f32); + } + NABufferType::AudioPacked(ref buf) => { + self.io.write_buf(buf.get_data().as_slice())?; + } + _ => {}, + }; + Ok(()) + } +} + +impl<'a> Drop for WavWriter<'a> { + #[allow(unused_variables)] + fn drop(&mut self) { + let size = self.io.tell(); + if (self.data_pos > 0) && (size >= self.data_pos) { + let res = self.io.seek(SeekFrom::Start(4)); + let res = self.io.write_u32le((size - 8) as u32); + let res = self.io.seek(SeekFrom::Start(self.data_pos - 4)); + let res = self.io.write_u32le(((size as u64) - self.data_pos) as u32); + } + } +}