Crate wavers

Source
Expand description

§Wavers

WaveRs is a fast and lightweight library for reading and writing wav files. Currently, it supports reading and writing of i16, i24, i32, f32, and f64 audio samples.

Feedback and bugs welcome!

§Highlights

  • Fast and lightweight
  • Simple API, read a wav file with read and write a wav file with write
  • Easy and efficient conversion between different types of audio samples (should compile down to simd instructions provided you build with the appropriate SIMD instruction set for your architecture).
  • Support for the Extensible format (Happy to try and support anything else that pops up, just ask or open a PR).
  • Increasing support for different chunks in the wav file.
  • Support for iteration over the frames, channels and overlapping blocks of the wav file.
  • Support for the ndarray crate. Enable the ndarray feature to enable ndarray support.
  • Support for the pyo3 crate. Enable the pyo3 feature to enable pyo3 support. This is mostly for PyWavers.
  • Supports logging through the log crate. Enable the logging feature to enable logging.

§Crate Status

  • This crate is currently in development. Changes to the core API will either not happen or they will be kept to a minimum. Any planned additions to the API will be built on top of the existing API.
  • Documentation is currently in progress, it is mostly complete but will be updated as necessary.
  • The API is tested, but there can always be more tests.
  • The crate has been benchmarked, but there can always be more benchmarks.
  • Some examples of planned features:
    • Investigate the performance of the write function.
    • Any suggestions or requests are welcome.

§Examples

The following examples show how to read and write a wav file, as well as retrieving information from the header.

§Reading

use wavers::{Wav, read};
use std::path::Path;

fn main() {
	let fp = "path/to/wav.wav";
    // creates a Wav file struct, does not read the audio data. Just the header information.
    let wav: Wav<i16> = Wav::from_path(fp).unwrap();
    // or to read the audio data directly
    let (samples, sample_rate): (Samples<i16>, i32) = read::<i16, _>(fp).unwrap();
    // samples can be derefed to a slice of samples
    let samples: &[i16] = &samples;
}

§Conversion

use wavers::{Wav, read, ConvertTo};
use std::path::Path;

fn main() {
    // Two ways of converted a wav file
    let fp: "./path/to/i16_encoded_wav.wav";
    let wav: Wav<f32> = Wav::from_path(fp).unwrap();
    // conversion happens automatically when you read
    let samples: &[f32] = &wav.read().unwrap();

    // or read and then call the convert function on the samples.
    let (samples, sample_rate): (Samples<i16>, i32) = read::<i16, _>(fp).unwrap();
    let samples: &[f32] = &samples.convert();
}

§Writing

use wavers::Wav;
use std::path::Path;

fn main() {
	let fp: &Path = &Path::new("path/to/wav.wav");
	let out_fp: &Path = &Path::new("out/path/to/wav.wav");

    // two main ways, read and write as the type when reading
    let wav: Wav<i16> = Wav::from_path(fp).unwrap();
    wav.write(out_fp).unwrap();

    // or read, convert, and write
    let (samples, sample_rate): (Samples<i16>,i32) = read::<i16, _>(fp).unwrap();
    let sample_rate = wav.sample_rate();
    let n_channels = wav.n_channels();

    let samples: &[f32] = &samples.convert();
    write(out_fp, samples, sample_rate, n_channels).unwrap();
}

§Iteration

WaveRs provides two primary methods of iteration: Frame-wise and Channel-wise. These can be performed using the Wav::frames and Wav::channels functions respectively. Both methods return an iterator over the samples in the wav file. The frames method returns an iterator over the frames of the wav file, where a frame is a single sample from each channel. The channels method returns an iterator over the channels of the wav file, where a channel is all the samples for a single channel.

use wavers::Wav;

fn main() {
    let wav = Wav::from_path("path/to/two_channel.wav").unwrap();
    for frame in wav.frames() {
       assert_eq!(frame.len(), 2, "The frame should have two samples since the wav file has two channels");
       // do something with the frame
    }

    for channel in wav.channels() {
        // do something with the channel
        assert_eq!(channel.len(), wav.n_samples() / wav.n_channels(), "The channel should have the same number of samples as the wav file divided by the number of channels");
    }
}

§Wav Utilities

use wavers::wav_spec;
fn main() {
    let fp = "path/to/wav.wav";
    let wav: Wav<i16> = Wav::from_path(fp).unwrap();
    let wav_spec = wav.wav_spec(); // returns the duration and the header
    println!("{:?}", wav_spec);
}

Check out wav_inspect for a simnple command line tool to inspect the headers of wav files.

§Features

The following section describes the features available in the WaveRs crate.

§Ndarray

The ndarray feature is used to provide functions that allow wav files to be read as ndarray 2-D arrays (samples x channels). There are two functions provided, into_ndarray and as_ndarray. into_ndarray consumes the samples and as_ndarray creates a Array2 from the samples.

use wavers::{read, Wav, AsNdarray, IntoNdarray, Samples};
use ndarray::{Array2, CowArray2};

fn main() {
	let fp = "path/to/wav.wav";
    let wav: Wav<i16> = Wav::from_path(fp).unwrap();

    // does not consume the wav file struct
	let (i16_array, sample_rate): (Array2<i16>, i32) = wav.as_ndarray().unwrap();
     
    // consumes the wav file struct
	let (i16_array, sample_rate): (Array2<i16>, i32) = wav.into_ndarray().unwrap();

    // convert the array to samples.
    let samples: Samples<i16> = Samples::from(i16_array);
}

§Benchmarks

To check out the benchmarks head on over to the benchmarks wiki page on the WaveRs GitHub. Benchmarks were conducted on the reading and writing functionality of WaveRs and compared to the hound crate.

Re-exports§

pub use crate::conversion::AudioSample;
pub use crate::conversion::ConvertSlice;
pub use crate::conversion::ConvertTo;
pub use crate::chunks::FactChunk;
pub use crate::chunks::FmtChunk;
pub use crate::chunks::ListChunk;
pub use crate::chunks::DATA;
pub use crate::chunks::FACT;
pub use crate::chunks::LIST;
pub use crate::chunks::RIFF;
pub use crate::chunks::WAVE;
pub use crate::core::wav_spec;
pub use crate::core::ReadSeek;
pub use crate::core::Samples;
pub use crate::core::Wav;
pub use crate::error::WaversError;
pub use crate::error::WaversResult;
pub use crate::header::WavHeader;
pub use crate::wav_type::format_info_to_wav_type;
pub use crate::wav_type::wav_type_to_format_info;
pub use crate::wav_type::FormatCode;
pub use crate::wav_type::WavType;

Modules§

chunks
This module contains the Chunk trait and the constants relating to the different chunks in a wav file.
conversion
core
error
Module containing the error types for Wavers
header
Module containing functions and structs for working with Wav file headers.
iter
Module containing the different type of iterators for the Wav struct.
wav_type
Module for the WavType enum and related functions.

Macros§

log
A macro for logging messages if the logging feature is enabled.

Functions§

read
Reads a wav file and returns the samples and the sample rate.
write
Writes wav samples to disk.