diff --git a/src/fmt.rs b/src/fmt.rs index c789c1a..aec3bab 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -1,5 +1,9 @@ use uuid::Uuid; use super::common_format::{CommonFormat, UUID_PCM,UUID_BFORMAT_PCM}; +use std::io::Cursor; + +use byteorder::LittleEndian; +use byteorder::WriteBytesExt; #[allow(dead_code)] @@ -181,7 +185,7 @@ pub struct WaveFmt { impl WaveFmt { - + pub fn valid_bits_per_sample(&self) -> u16 { if let Some(ext) = self.extended_format { ext.valid_bits_per_sample @@ -274,6 +278,46 @@ impl WaveFmt { vec![0i32; self.channel_count as usize] } + /// Calculate the size of a byte buffer needed to hold audio data of this + /// format for a given number of frames + pub fn buffer_length(&self, frame_count: u64) -> usize { + (self.block_alignment as u64 * frame_count) as usize + } + + // Write frames into a byte vector + pub fn pack_frames(&self, from_frames: &[i32], into_bytes: &mut Vec) -> () { + let mut write_cursor = Cursor::new(into_bytes); + + assert!(from_frames.len() % self.channel_count as usize == 0, + "frames buffer does not contain a number of samples % channel_count == 0"); + + for n in 0..from_frames.len() { + match (self.valid_bits_per_sample(), self.bits_per_sample) { + (0..=8,8) => write_cursor.write_u8((from_frames[n] + 0x80) as u8 ).unwrap(), // EBU 3285 §A2.2 + (9..=16,16) => write_cursor.write_i16::(from_frames[n] as i16).unwrap(), + (10..=24,24) => write_cursor.write_i24::(from_frames[n]).unwrap(), + (25..=32,32) => write_cursor.write_i32::(from_frames[n]).unwrap(), + (b,_)=> panic!("Unrecognized integer format, bits per sample {}, channels {}, block_alignment {}", + b, self.channel_count, self.block_alignment) + } + } + () + } + + /// Read bytes into frames + // pub fn unpack_frames(&self, from_bytes: &[u8], into_frames: &mut Vec) -> () { + // for n in 0..(from_bytes.len()) { + // buffer[n] = match (self.format.bits_per_sample, framed_bits_per_sample) { + // (0..=8,8) => self.inner.read_u8()? as i32 - 0x80_i32, // EBU 3285 §A2.2 + // (9..=16,16) => self.inner.read_i16::()? as i32, + // (10..=24,24) => self.inner.read_i24::()?, + // (25..=32,32) => self.inner.read_i32::()?, + // (b,_)=> panic!("Unrecognized integer format, bits per sample {}, channels {}, block_alignment {}", + // b, self.format.channel_count, self.format.block_alignment) + // } + // } + // } + /// Channel descriptors for each channel. pub fn channels(&self) -> Vec { diff --git a/src/wavewriter.rs b/src/wavewriter.rs index cdec19a..151f9c9 100644 --- a/src/wavewriter.rs +++ b/src/wavewriter.rs @@ -16,48 +16,23 @@ use byteorder::WriteBytesExt; /// /// pub struct AudioFrameWriter where W: Write + Seek { - inner : WaveChunkWriter, - framed_bits_per_sample : u16, - bits_per_sample: u16, - channel_count: u16, - block_alignment: u16, + inner : WaveChunkWriter } impl AudioFrameWriter where W: Write + Seek { fn new(inner: WaveChunkWriter) -> Self { - let fbps = inner.inner.format.bits_per_sample; - let ba = inner.inner.format.block_alignment; - let cc = inner.inner.format.channel_count; - let bps = inner.inner.format.valid_bits_per_sample(); - AudioFrameWriter { - inner, - framed_bits_per_sample: fbps, - bits_per_sample: bps, - channel_count: cc, - block_alignment: ba, - } + AudioFrameWriter { inner } } fn write_integer_frames_to_buffer(&self, from_frames :&[i32], to_buffer : &mut Vec) -> () { - let mut write_cursor = Cursor::new(to_buffer); - - assert!(from_frames.len() % self.channel_count as usize == 0, + assert!(from_frames.len() % self.inner.inner.format.channel_count as usize == 0, "frames buffer does not contain a number of samples % channel_count == 0"); - - for n in 0..from_frames.len() { - match (self.bits_per_sample, self.framed_bits_per_sample) { - (0..=8,8) => write_cursor.write_u8((from_frames[n] + 0x80) as u8 ).unwrap(), // EBU 3285 §A2.2 - (9..=16,16) => write_cursor.write_i16::(from_frames[n] as i16).unwrap(), - (10..=24,24) => write_cursor.write_i24::(from_frames[n]).unwrap(), - (25..=32,32) => write_cursor.write_i32::(from_frames[n]).unwrap(), - (b,_)=> panic!("Unrecognized integer format, bits per sample {}, channels {}, block_alignment {}", - b, self.channel_count, self.block_alignment) - } - } + self.inner.inner.format.pack_frames(&from_frames, to_buffer); () } + /// Write interleaved samples in `buffer` pub fn write_integer_frames(&mut self, buffer: &[i32]) -> Result { let mut write_buffer = vec![0u8; 0]; @@ -65,11 +40,9 @@ impl AudioFrameWriter where W: Write + Seek { self.inner.write(&write_buffer)?; self.inner.flush()?; - Ok(write_buffer.len() as u64 / self.channel_count as u64) + Ok(write_buffer.len() as u64 / self.inner.inner.format.channel_count as u64) } - - /// Finish writing audio frames and unwrap the inner `WaveWriter`. /// /// This method must be called when the client has finished writing audio @@ -421,7 +394,7 @@ fn test_write_bext() { // NOTE! This test of RF64 writing passes on my machine but because it takes // nearly 5 mins to run I have omitted it from the source for now... -#[test] +//#[test] fn test_create_rf64() { use std::io::Cursor; use super::fourcc::ReadFourCC;