X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=src%2Fwavwriter.rs;h=ab26f6c9ee0727cc9bcfc2d0aa3d063728fc6f2a;hb=081797c71bd8cd4342d58a2124cbd7f72d02b7d2;hp=fbf825d88e79046a4f0dd01349472fb2175b92d0;hpb=bcaa61dbe363c0fef533285d02789c2b4994425e;p=nihav-tool.git diff --git a/src/wavwriter.rs b/src/wavwriter.rs index fbf825d..ab26f6c 100644 --- a/src/wavwriter.rs +++ b/src/wavwriter.rs @@ -8,6 +8,8 @@ use std::io::SeekFrom; pub struct WavWriter<'a> { io: Box>, data_pos: u64, + be: bool, + bits: u8, } fn write_byte(wr: &mut ByteWriter, sample: u8) -> ByteIOResult<()> { @@ -59,9 +61,10 @@ macro_rules! write_data { impl<'a> WavWriter<'a> { pub fn new(name: &str) -> Self { let file = File::create(name).unwrap(); + let file = std::io::BufWriter::new(file); let fw = Box::new(FileWriter::new_write(file)); let io = ByteWriter::new(Box::leak(fw)); - WavWriter { io: Box::new(io), data_pos: 0 } + WavWriter { io: Box::new(io), data_pos: 0, be: false, bits: 0 } } pub fn write_header(&mut self, ainfo: NAAudioInfo) -> ByteIOResult<()> { let bits = ainfo.get_format().get_bits() as usize; @@ -76,7 +79,7 @@ impl<'a> WavWriter<'a> { self.io.write_u16le(ainfo.get_channels() as u16)?; self.io.write_u32le(ainfo.get_sample_rate() as u32)?; - if bits < 16 { + if bits <= 8 { 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)?; @@ -89,6 +92,8 @@ impl<'a> WavWriter<'a> { self.io.write_buf(b"data")?; self.io.write_u32le(0)?; + self.bits = bits as u8; + self.be = ainfo.get_format().is_be(); self.data_pos = self.io.tell(); Ok(()) } @@ -107,7 +112,51 @@ impl<'a> WavWriter<'a> { write_data!(&mut self.io, buf, write_f32); } NABufferType::AudioPacked(ref buf) => { - self.io.write_buf(buf.get_data().as_slice())?; + let data = buf.get_data(); + match self.bits { + _ if !self.be && (self.bits & 7) == 0 => { + self.io.write_buf(data.as_slice())?; + }, + 8 => { + self.io.write_buf(data.as_slice())?; + }, + 12 if !self.be => { + let mut src = data.chunks_exact(3); + while let Some(chunk) = src.next() { + self.io.write_byte(chunk[0] << 4)?; + self.io.write_byte((chunk[1] << 4) | (chunk[0] >> 4))?; + self.io.write_byte(chunk[1] & 0xF0)?; + self.io.write_byte(chunk[2])?; + } + let tail = src.remainder(); + if tail.len() == 2 { + self.io.write_byte(tail[0] << 4)?; + self.io.write_byte(tail[1] << 4)?; + } + } + 16 => { + for samp in data.chunks(2) { + self.io.write_byte(samp[1])?; + self.io.write_byte(samp[0])?; + } + }, + 24 => { + for samp in data.chunks(3) { + self.io.write_byte(samp[2])?; + self.io.write_byte(samp[1])?; + self.io.write_byte(samp[0])?; + } + }, + 32 => { + for samp in data.chunks(4) { + self.io.write_byte(samp[3])?; + self.io.write_byte(samp[2])?; + self.io.write_byte(samp[1])?; + self.io.write_byte(samp[0])?; + } + }, + _ => unimplemented!(), + }; } _ => {}, }; @@ -124,6 +173,7 @@ impl<'a> Drop for WavWriter<'a> { 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); + let res = self.io.flush(); } } }