rework WAV writer a bit and add 12-bit PCM support
[nihav-tool.git] / src / wavwriter.rs
index c0b324dc19215288151e3d500c4234ae99f9b5dd..ab26f6c9ee0727cc9bcfc2d0aa3d063728fc6f2a 100644 (file)
@@ -79,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)?;
@@ -112,35 +112,51 @@ impl<'a> WavWriter<'a> {
                 write_data!(&mut self.io, buf, write_f32);
             }
             NABufferType::AudioPacked(ref buf) => {
-                if !self.be || self.bits == 8 {
-                    self.io.write_buf(buf.get_data().as_slice())?;
-                } else {
-                    let data = buf.get_data();
-                    match self.bits {
-                        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!(),
-                    };
-                }
+                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!(),
+                };
             }
             _ => {},
         };