mirror of
https://github.com/iluvcapra/bwavfile.git
synced 2025-12-31 08:50:44 +00:00
Format implementation
This commit is contained in:
@@ -10,14 +10,14 @@ Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support
|
||||
|
||||
This is currently a work-in-progress! However many features presently work:
|
||||
|
||||
| Feature | Read | Write |
|
||||
|---------------------------------------|:-----:|:-----:|
|
||||
| Feature |Read |Write|
|
||||
|---------------------------------------|:---:|:-----:|
|
||||
| Standard .wav files | ☑️ | ☑ ️ |
|
||||
| Transparent promotion to RF64/BW64 | ☑️ | |
|
||||
| Unified interface for regular and extended Wave format | ☑️ | |
|
||||
| Channel/speaker map metadata | ☑️ | |
|
||||
| Channel/speaker map metadata | ☑️ | ☑️ |
|
||||
| Ambisonic B-format metadata | ☑️ | |
|
||||
| EBU Broadcast-WAVE metadata | ☑️ | |
|
||||
| EBU Broadcast-WAVE metadata | ☑️ | ☑️ |
|
||||
| Basic iXML/ADM metadata | ☑️ | |
|
||||
| Enhanced iXML metadata support | | |
|
||||
| Broadcast-WAVE Level overview `levl` metadata | | |
|
||||
|
||||
57
src/fmt.rs
57
src/fmt.rs
@@ -181,36 +181,57 @@ pub struct WaveFmt {
|
||||
|
||||
|
||||
impl WaveFmt {
|
||||
|
||||
/// Create a new integer PCM format for a monoaural audio stream.
|
||||
pub fn new_pcm_mono(sample_rate: u32, bits_per_sample: u16) -> Self {
|
||||
Self::new_pcm_multichannel(sample_rate, bits_per_sample, 0x4)
|
||||
}
|
||||
|
||||
/// Create a new integer PCM format `WaveFmt`
|
||||
pub fn new_pcm(sample_rate: u32, bits_per_sample: u16, channel_count: u16) -> Self {
|
||||
/// Create a new integer PCM format for a standard Left-Right stereo audio
|
||||
/// stream.
|
||||
pub fn new_pcm_stereo(sample_rate: u32, bits_per_sample: u16) -> Self {
|
||||
Self::new_pcm_multichannel(sample_rate, bits_per_sample, 0x3)
|
||||
}
|
||||
|
||||
/// Create a new integer PCM format for ambisonic b-format.
|
||||
pub fn new_pcm_ambisonic(sample_rate: u32, bits_per_sample: u16, channel_count: u16) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new integer PCM format `WaveFmt` with a custom channel bitmap.
|
||||
///
|
||||
/// The order of `channels` is not important. When reading or writing
|
||||
/// audio frames you must use the standard multichannel order for Wave
|
||||
/// files, the numerical order of the cases of `ChannelMask`.
|
||||
pub fn new_pcm_multichannel(sample_rate: u32, bits_per_sample: u16, channel_bitmap: u32) -> Self {
|
||||
let container_bits_per_sample = bits_per_sample + (bits_per_sample % 8);
|
||||
let container_bytes_per_sample= container_bits_per_sample / 8;
|
||||
|
||||
let channel_count: u16 = (0..=31).fold(0u16, |accum, n| accum + (0x1 & (channel_bitmap >> n) as u16) );
|
||||
|
||||
let tag : u16 = match channel_count {
|
||||
1..=2 => 0x01,
|
||||
x if x > 2 => 0xFFFE,
|
||||
x => panic!("Invalid channel count {}", x)
|
||||
let result : (u16, Option<WaveFmtExtended>) = match channel_bitmap {
|
||||
ch if bits_per_sample != container_bits_per_sample => (
|
||||
(0xFFFE, Some(WaveFmtExtended { valid_bits_per_sample: bits_per_sample, channel_mask: ch,
|
||||
type_guid: UUID_PCM }) )
|
||||
),
|
||||
0b0100 => (0x0001, None),
|
||||
0b0011 => (0x0001, None),
|
||||
ch => (
|
||||
(0xFFFE, Some( WaveFmtExtended { valid_bits_per_sample: bits_per_sample, channel_mask: ch,
|
||||
type_guid: UUID_PCM}))
|
||||
)
|
||||
};
|
||||
|
||||
let (tag, extformat) = result;
|
||||
|
||||
WaveFmt {
|
||||
tag,
|
||||
tag,
|
||||
channel_count,
|
||||
sample_rate,
|
||||
bytes_per_second: container_bytes_per_sample as u32 * sample_rate * channel_count as u32,
|
||||
block_alignment: container_bytes_per_sample * channel_count,
|
||||
bits_per_sample: container_bits_per_sample,
|
||||
extended_format: {
|
||||
if channel_count > 2 {
|
||||
Some( WaveFmtExtended {
|
||||
channel_mask : !(0xFFFF_FFFF << channel_count),
|
||||
type_guid: UUID_PCM,
|
||||
valid_bits_per_sample: bits_per_sample
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
extended_format: extformat
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ impl<W> Write for WaveChunkWriter<W> where W: Write + Seek {
|
||||
///
|
||||
/// // Write a three-sample wave file to a cursor
|
||||
/// let mut cursor = Cursor::new(vec![0u8;0]);
|
||||
/// let format = WaveFmt::new_pcm(48000, 24, 1);
|
||||
/// let format = WaveFmt::new_pcm_mono(48000, 24);
|
||||
/// let w = WaveWriter::new(&mut cursor, format).unwrap();
|
||||
///
|
||||
/// let mut frame_writer = w.audio_frame_writer().unwrap();
|
||||
@@ -183,16 +183,13 @@ impl<W> WaveWriter<W> where W: Write + Seek {
|
||||
Ok( retval )
|
||||
}
|
||||
|
||||
/// Create a new chunk writer, which takes posession of the `WaveWriter`.
|
||||
///
|
||||
/// Begin writing a chunk segment. To close the chunk (and perhaps write
|
||||
/// another), call `end()` on the chunk writer.
|
||||
|
||||
fn chunk(mut self, ident: FourCC) -> Result<WaveChunkWriter<W>,Error> {
|
||||
self.inner.seek(SeekFrom::End(0))?;
|
||||
WaveChunkWriter::begin(self, ident)
|
||||
}
|
||||
|
||||
/// Write Broadcast-Wave metadata to the file.Bext
|
||||
/// Write Broadcast-Wave metadata to the file.
|
||||
///
|
||||
/// This function will write the metadata chunk immediately; if you have
|
||||
/// already written and closed the audio data the bext chunk will be
|
||||
@@ -244,7 +241,7 @@ fn test_new() {
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
let mut cursor = Cursor::new(vec![0u8;0]);
|
||||
let format = WaveFmt::new_pcm(4800, 24, 1);
|
||||
let format = WaveFmt::new_pcm_mono(4800, 24);
|
||||
WaveWriter::new(&mut cursor, format).unwrap();
|
||||
|
||||
cursor.seek(SeekFrom::Start(0)).unwrap();
|
||||
@@ -270,7 +267,7 @@ fn test_write_audio() {
|
||||
use byteorder::ReadBytesExt;
|
||||
|
||||
let mut cursor = Cursor::new(vec![0u8;0]);
|
||||
let format = WaveFmt::new_pcm(48000, 24, 1);
|
||||
let format = WaveFmt::new_pcm_mono(48000, 24);
|
||||
let w = WaveWriter::new(&mut cursor, format).unwrap();
|
||||
|
||||
let mut frame_writer = w.audio_frame_writer().unwrap();
|
||||
@@ -316,7 +313,7 @@ fn test_write_bext() {
|
||||
use std::io::Cursor;
|
||||
|
||||
let mut cursor = Cursor::new(vec![0u8;0]);
|
||||
let format = WaveFmt::new_pcm(48000, 24, 1);
|
||||
let format = WaveFmt::new_pcm_mono(48000, 24);
|
||||
let w = WaveWriter::new(&mut cursor, format).unwrap();
|
||||
|
||||
let bext = Bext {
|
||||
|
||||
Reference in New Issue
Block a user