Skip to main content

Overview

Symphonia provides a pure Rust implementation of the Apple Lossless Audio Codec (ALAC) decoder. ALAC is a lossless audio compression format developed by Apple, commonly used in M4A and CAF containers.

Feature Flag

To enable ALAC support, add the alac feature to your Cargo.toml:
[dependencies]
symphonia = { version = "0.5", features = ["alac"] }
Or use the standalone crate:
[dependencies]
symphonia-codec-alac = "0.5"

Status

Status: Excellent
  • Decoding: Fully supported
  • Gapless Playback: Yes
  • Container Support: ISO MP4/M4A, CAF (Core Audio Format)

Codec Type

use symphonia::core::codecs::CODEC_TYPE_ALAC;

Decoder

The ALAC decoder is implemented by the AlacDecoder struct:
use symphonia_codec_alac::AlacDecoder;
use symphonia::core::codecs::{Decoder, DecoderOptions};

// Create decoder from codec parameters
let mut decoder = AlacDecoder::try_new(&codec_params, &DecoderOptions::default())?;

// Decode a packet
let decoded = decoder.decode(&packet)?;

Container Requirements

ALAC requires a container format:
[dependencies]
# For M4A files (most common)
symphonia = { version = "0.5", features = ["alac", "isomp4"] }

# For CAF files
symphonia = { version = "0.5", features = ["alac", "caf"] }

Supported Features

ALAC Version

  • ALAC Version 0 (current standard)

Bit Depths

  • 16-bit
  • 20-bit
  • 24-bit
  • 32-bit

Sample Rates

All sample rates up to 384 kHz, including:
  • 8 kHz, 11.025 kHz, 12 kHz
  • 16 kHz, 22.05 kHz, 24 kHz
  • 32 kHz, 44.1 kHz, 48 kHz
  • 88.2 kHz, 96 kHz
  • 176.4 kHz, 192 kHz
  • 352.8 kHz, 384 kHz

Channel Layouts

Supports standard Apple Core Audio channel layouts:
  • Mono (1.0): C
  • Stereo (2.0): L, R
  • MPEG 3.0 B: C, L, R
  • MPEG 4.0 B: C, L, R, Cs
  • MPEG 5.0 D: C, L, R, Ls, Rs
  • MPEG 5.1 D: C, L, R, Ls, Rs, LFE
  • AAC 6.1: C, L, R, Ls, Rs, Cs, LFE
  • MPEG 7.1 B: C, Lc, Rc, L, R, Ls, Rs, LFE
Up to 8 channels supported.

Codec Parameters

ALAC requires codec-specific configuration (“magic cookie”):
// The magic cookie is automatically parsed from extra_data
// in the codec parameters provided by the container

let codec_params = &track.codec_params;

// These parameters are available:
codec_params.sample_rate;        // Sample rate
codec_params.channels;           // Channel configuration
codec_params.bits_per_sample;    // Bit depth
codec_params.max_frames_per_packet; // Frame length
The magic cookie contains:
  • Frame length (samples per frame)
  • Compatible version
  • Bit depth
  • Compression parameters (pb, mb, kb)
  • Number of channels
  • Maximum frame size
  • Average bitrate
  • Sample rate
  • Channel layout information (optional)

Compression Modes

ALAC supports multiple prediction methods:

Prediction Types

  • Uncompressed: Raw PCM samples
  • Linear Prediction: LPC with orders up to 31
  • Adaptive Prediction: Automatic coefficient adjustment

Encoding Elements

  • SCE: Single Channel Element (mono)
  • CPE: Channel Pair Element (stereo pairs)
  • LFE: Low Frequency Element (subwoofer)

Usage Example

use symphonia::core::codecs::{CODEC_TYPE_ALAC, DecoderOptions};
use symphonia::core::formats::FormatOptions;
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use std::fs::File;

fn decode_alac_file(path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // Open the media source
    let file = Box::new(File::open(path)?);
    let mss = MediaSourceStream::new(file, Default::default());

    // Create a hint
    let mut hint = Hint::new();
    hint.with_extension("m4a");

    // Probe the media source
    let probed = symphonia::default::get_probe()
        .format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())?;

    let mut format = probed.format;

    // Find the ALAC track
    let track = format.tracks()
        .iter()
        .find(|t| t.codec_params.codec == CODEC_TYPE_ALAC)
        .ok_or("No ALAC track found")?;

    println!("Sample Rate: {:?}", track.codec_params.sample_rate);
    println!("Channels: {:?}", track.codec_params.channels);
    println!("Bit Depth: {:?}", track.codec_params.bits_per_sample);

    // Create the decoder
    let mut decoder = symphonia::default::get_codecs()
        .make(&track.codec_params, &DecoderOptions::default())?;

    // Decode packets
    loop {
        let packet = match format.next_packet() {
            Ok(packet) => packet,
            Err(_) => break,
        };

        if packet.track_id() != track.id {
            continue;
        }

        let decoded = decoder.decode(&packet)?;
        // Process decoded audio (lossless PCM)...
    }

    Ok(())
}

Sample Format

ALAC decodes to signed 32-bit integer samples:
use symphonia::core::audio::AudioBufferRef;

let decoded = decoder.decode(&packet)?;

match decoded {
    AudioBufferRef::S32(buf) => {
        // Access i32 samples
        for channel in 0..buf.spec().channels.count() {
            let samples = buf.chan(channel);
            // Samples are left-aligned to 32-bit
            // For 16-bit source: use top 16 bits
            // For 24-bit source: use top 24 bits
        }
    }
    _ => unreachable!("ALAC always decodes to S32"),
}

Metadata Support

ALAC files in MP4 containers support iTunes metadata:
use symphonia::core::meta::MetadataOptions;

let probed = symphonia::default::get_probe()
    .format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())?;

// Access iTunes metadata
if let Some(metadata_rev) = probed.format.metadata().current() {
    for tag in metadata_rev.tags() {
        println!("{}: {}", tag.key, tag.value);
    }
    
    // Access embedded artwork
    for visual in metadata_rev.visuals() {
        println!("Cover art: {} bytes", visual.data.len());
    }
}

Rice Coding

ALAC uses adaptive Rice coding for efficient lossless compression:
  • Dynamic parameter selection
  • Run-length encoding for silence
  • Efficient representation of prediction residuals

Performance

  • Pure Rust implementation with no unsafe code
  • Efficient Rice decoder
  • Optimized LPC predictor
  • Low memory overhead
  • Streaming-friendly design

Limitations

  • Decode-only (no encoding support)
  • Maximum 8 channels
  • Requires container format (cannot decode raw ALAC)
  • ALAC Version 0 only (latest version)

Comparison with Other Lossless Codecs

FeatureALACFLAC
Compression~40-50%~40-60%
SpeedFastFast
Max Bit Depth32-bit32-bit
Max Channels88 (Symphonia)
iTunes SupportNativeLimited

Documentation

See Also

Build docs developers (and LLMs) love