From dea68662f8fdd39fc888942196e75114ae66c63c Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 22 Nov 2020 23:32:25 -0800 Subject: [PATCH] Comments and documentation --- src/audio_frame_reader.rs | 19 +++++++++++++++- src/lib.rs | 47 ++++++++++++++++++++++++++++++++++----- src/validation.rs | 29 +++++++++++++++--------- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/audio_frame_reader.rs b/src/audio_frame_reader.rs index c891fda..89e208c 100644 --- a/src/audio_frame_reader.rs +++ b/src/audio_frame_reader.rs @@ -7,7 +7,10 @@ use byteorder::ReadBytesExt; use super::chunks::WaveFmt; use super::errors::Error; -/// Read samples from a `WaveFileReader` +/// Read audio frames +/// +/// The inner reader is interpreted as a raw audio data +/// bitstream having a format specified by `format`. /// #[derive(Debug)] pub struct AudioFrameReader { @@ -18,6 +21,13 @@ pub struct AudioFrameReader { impl AudioFrameReader { /// Create a new `AudioFrameReader` + /// + /// ### Panics + /// + /// This method does a few sanity checks on the provided format + /// parameter to confirm the `block_alignment` law is fulfilled + /// and the format tag is readable by this implementation (only + /// format 0x01 is supported at this time.) pub fn new(inner: R, format: WaveFmt) -> Self { assert!(format.block_alignment * 8 == format.bits_per_sample * format.channel_count, "Unable to read audio frames from packed formats: block alignment is {}, should be {}", @@ -28,6 +38,8 @@ impl AudioFrameReader { } /// Locate the read position to a different frame + /// + /// Seeks within the audio stream. pub fn locate(&mut self, to :u64) -> Result { let position = to * self.format.block_alignment as u64; let seek_result = self.inner.seek(Start(position))?; @@ -46,6 +58,11 @@ impl AudioFrameReader { /// /// A single frame is read from the audio stream and the read location /// is advanced one frame. + /// + /// ### Panics + /// + /// The `buffer` must have a number of elements equal to the number of + /// channels and this method will panic if this is not the case. pub fn read_integer_frame(&mut self, buffer:&mut [i32]) -> Result { assert!(buffer.len() as u16 == self.format.channel_count, "read_integer_frame was called with a mis-sized buffer, expected {}, was {}", diff --git a/src/lib.rs b/src/lib.rs index 9cd1997..fdae856 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,49 @@ -// /*! # bwavfile Rust Wave File Reader/Writer with Broadcast-WAV, MBWF and RF64 Support -(Note: This crate is still in an alpha or pre-alpha stage of development. Reading of +__(Note: This crate is still in an alpha or pre-alpha stage of development. Reading of files works however the interfaces may change significantly. Stay up-to-date on the -status of this project at [Github][github].) +status of this project at [Github][github].)__ + +## Objectives and Roadmap + +This package aims to support read and writing any kind of WAV file you are likely +to encounter in a professional audio, motion picture production, broadcast, or music +production. + +Apps we test against: +- Avid Pro Tools +- FFMpeg +- Audacity + +Wave features we want to support with maximum reliability and ease of use: + +- Large file size, RF64 support +- Multichannel audio formats +- Embedded metadata + +In addition to reading the audio, we want to support all of the different +metadata planes you are liable to need to use. + +- Broadcast-WAV metadata (including the SMPTE UMID and EBU v2 extensions) +- iXML Production recorder metadata +- ADM XML (with associated `chna` mappings) +- Dolby metadata block + +Things that are _not_ necessarily in the scope of this package: + +- Broad codec support. There are a little more than one-hundred + [registered wave codecs][rfc3261], but because this library is targeting + professional formats being created today, we only plan on supporting + two of them: tag 0x0001 (Integer Linear PCM) and tag 0x0003 (IEEE Float + Linear PCM). +- Music library metadata. There are several packages that can read ID3 + metadata and it's not particuarly common in wave files in any case. INFO + metadata is more common though in professional applications it tends not + to be used by many applications. + ## Resources @@ -15,9 +52,9 @@ status of this project at [Github][github].) ### Implementation of 64-bit Wave Files - [ITU-R 2088][itu2088] (October 2019), "Long-form file format for the international exchange of audio programme materials with metadata" - - Presently in force, adopted by the EBU in [EBU Tech 3306v2][ebu3306v2] (June 2018). + - Presently in force, adopted by the EBU in [EBU Tech 3306v2][ebu3306v2] (June 2018). - [EBU Tech 3306v1][ebu3306v1] (July 2009), "MBWF / RF64: An extended File Format for Audio" - - No longer in force, however long-established. + - No longer in force, however long-established. ### Implementation of Wave format `fmt` chunk diff --git a/src/validation.rs b/src/validation.rs index a823436..0022864 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -5,12 +5,15 @@ use super::wavereader::{WaveReader}; use std::io::{Read,Seek}; + impl WaveReader { /** - * Returns without `Err` if the source meets the minimum standard of + * Validate file is readable. + * + * `Ok(())` if the source meets the minimum standard of * readability by a permissive client: - * 1. `fmt` chunk and `data` chunk are present - * 1. `fmt` chunk appears before `data` chunk + * - `fmt` chunk and `data` chunk are present + * - `fmt` chunk appears before `data` chunk */ pub fn validate_readable(&mut self) -> Result<(), ParserError> { let (fmt_pos, _) = self.get_chunk_extent_at_index(FMT__SIG, 0)?; @@ -24,9 +27,9 @@ impl WaveReader { } /** - * Validate minimal WAVE file + * Validate minimal WAVE file. * - * Returns without `Err` the source is `validate_readable` AND + * `Ok(())` if the source is `validate_readable()` AND * * - Contains _only_ a `fmt` chunk and `data` chunk, with no other chunks present * - is not an RF64/BW64 @@ -34,6 +37,8 @@ impl WaveReader { * Some clients require a WAVE file to only contain format and data without any other * metadata and this function is provided to validate this condition. * + * ### Examples + * * ``` * # use bwavfile::WaveReader; * @@ -64,9 +69,11 @@ impl WaveReader { /** * Validate Broadcast-WAVE file format * - * Returns without `Err` if `validate_readable()` and file contains a + * Returns `Ok(())` if `validate_readable()` and file contains a * Broadcast-WAV metadata record (a `bext` chunk). * + * ### Examples + * * ``` * # use bwavfile::WaveReader; * @@ -87,9 +94,9 @@ impl WaveReader { } /** - * Verify data is aligned to a block boundary + * Verify data is aligned to a block boundary. * - * Returns without `Err` if `validate_readable()` and the start of the + * Returns `Ok(())` if `validate_readable()` and the start of the * `data` chunk's content begins at 0x4000. */ pub fn validate_data_chunk_alignment(&mut self) -> Result<() , ParserError> { @@ -103,10 +110,12 @@ impl WaveReader { } /** - * Returns without `Err` if: + * Verify audio data can be appended immediately to this file. + * + * Returns `Ok(())` if: * - `validate_readable()` * - there is a `JUNK` or `FLLR` immediately at the beginning of the chunk - * list adequately large enough to be overwritten by a `ds64` (96 bytes) + * list adequately large enough to be overwritten by a `ds64` (92 bytes) * - `data` is the final chunk */ pub fn validate_prepared_for_append(&mut self) -> Result<(), ParserError> {