Skip to content

Repository files navigation

audio-file

A simple library to read and write audio files on your disk.

The library can read many formats and can write only to wav files.

Quick Start

Read a file into interleaved f32 (or f64) samples, full scale at ±1.0:

let audio = audio_file::read::<f32>("test_data/test_1ch.wav", audio_file::ReadConfig::default())?;

let samples = &audio.samples_interleaved;
let sample_rate = audio.sample_rate;
let num_channels = audio.num_channels;

Write interleaved samples back out as a wav file:

let samples = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]; // interleaved
let num_channels = 2;
let sample_rate = 48_000;

audio_file::write(
    "output.wav",
    &samples,
    num_channels,
    sample_rate,
    audio_file::WriteConfig::default(),
)?;

That covers most uses. Everything below is optional.

Features

With no default features, this crate reads and writes wav through a built-in decoder, with almost no dependencies. Everything else is additive on top of that.

Feature Default What it adds
all-codecs yes Read every common codec: MP3, FLAC, AAC, ALAC, Vorbis, and the MP4, Ogg, Matroska, AIFF and CAF containers
resample yes Resample while reading, via rubato
simd yes Symphonia's SIMD optimizations. Only does something alongside a codec feature
audio-blocks no Read and write any channel layout, via audio-blocks

Turning a feature off removes the API it brings rather than making it fail at runtime. Without resample, ReadConfig has no sample_rate field at all, so asking for a rate nothing would resample to does not compile.

Reading

ReadConfig selects what to read. Only the selected frames are stored, though the reader may decode and discard earlier packets for accurate seeking and codec warm-up.

Positions are given as a Position, in frames or in time. start is inclusive and stop is exclusive, so frame 300 to 400 yields 100 frames. Frame 0 is the first playable frame: encoder delay and padding, as used by formats like MP3, are not part of the timeline.

// the first half second
let audio = audio_file::read::<f32>(
    "test_data/test_1ch.wav",
    audio_file::ReadConfig {
        stop: audio_file::Position::Time(Duration::from_secs_f32(0.5)),
        ..Default::default()
    },
)?;

// frame 300 up to frame 400
let audio = audio_file::read::<f32>(
    "test_data/test_1ch.wav",
    audio_file::ReadConfig {
        start: audio_file::Position::Frame(300),
        stop: audio_file::Position::Frame(400),
        ..Default::default()
    },
)?;

Channels are selected the same way, with start_channel and num_channels:

// the first two channels
let audio = audio_file::read::<f32>(
    "test_data/test_4ch.wav",
    audio_file::ReadConfig {
        num_channels: Some(2),
        ..Default::default()
    },
)?;

// channel 2 and 3, skipping the first
let audio = audio_file::read::<f32>(
    "test_data/test_4ch.wav",
    audio_file::ReadConfig {
        start_channel: Some(1),
        num_channels: Some(2),
        ..Default::default()
    },
)?;

With the resample feature, a sample_rate makes the reader hand back audio at that rate whatever the file holds:

let audio = audio_file::read::<f32>(
    "test_data/test_1ch.wav",
    audio_file::ReadConfig {
        sample_rate: Some(22_050),
        ..Default::default()
    },
)?;

A file is either read in full or not at all: a packet the decoder rejects fails the whole read rather than being skipped over or filled in.

Writing

Output is always wav. WriteConfig picks the sample format:

SampleFormat Description
Int8 8-bit integer
Int16 16-bit integer (default, for the broadest compatibility)
Int32 32-bit integer
Float32 32-bit float
audio_file::write(
    "output_float32.wav",
    &samples_interleaved,
    num_channels,
    sample_rate,
    audio_file::WriteConfig {
        sample_format: audio_file::SampleFormat::Float32,
    },
)?;

Other channel layouts

Interleaved is the only layout read and write speak. With the audio-blocks feature you get read_block and write_block, which work in AudioBlocks and so handle any layout, plus channel-wise access to what was read:

let (block, sample_rate) =
    audio_file::read_block::<f32>("test_data/test_4ch.wav", ReadConfig::default())?;
let left: Vec<f32> = block.channel_iter(0).copied().collect();

let block = Sequential::from_slice(&[0.0, 0.0, 0.0, 1.0, 1.0, 1.0], 2);
audio_file::write_block("output_layout.wav", block, 48_000, WriteConfig::default())?;

Picking individual codecs

all-codecs is a convenience for "read anything". To keep the dependency tree small, name only the formats you need instead:

Format Feature flags
WAV, integer PCM and IEEE float none, built in
WAV, A-law, mu-law and ADPCM wav-compressed
FLAC flac
MP1, MP2, MP3 mp1, mp2, mp3
AAC (raw ADTS) aac
MP4, M4A isomp4 plus aac or alac
Ogg ogg plus vorbis or flac
Matroska (MKA, MKV) mkv plus the codec inside: pcm, flac, vorbis, aac, alac
AIFF aiff plus pcm
CAF caf plus pcm or alac

A container and the codec inside it are separate flags, so a format that can hold several codecs needs one of each. Enabling only the container reads no file at all. A file no decoder in the build can read fails with ReadError::UnsupportedFormat.

Some formats have channel ceilings below what the format itself allows, see the reader module docs.

About

Read and write audio files

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages