add wav output dumper for tests
authorKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 15 Jun 2017 12:32:54 +0000 (14:32 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 15 Jun 2017 12:32:54 +0000 (14:32 +0200)
src/lib.rs
src/test/mod.rs [new file with mode: 0644]
src/test/wavwriter.rs [new file with mode: 0644]

index 90001d79fc23c4f7dd11ced1ae83a248aa295b5b..c0ae9758579c5cc08aaa5a3a14b88b8006fa7a16 100644 (file)
@@ -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 (file)
index 0000000..a8fa2dc
--- /dev/null
@@ -0,0 +1 @@
+pub mod wavwriter;
diff --git a/src/test/wavwriter.rs b/src/test/wavwriter.rs
new file mode 100644 (file)
index 0000000..a68075e
--- /dev/null
@@ -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<usize> = 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);
+        }
+    }
+}