Metadata-Version: 2.4
Name: mlx-audio-io
Version: 1.3.24
Summary: Native audio I/O for MLX on macOS and Linux
License-Expression: MIT
Project-URL: Repository, https://github.com/ssmall256/mlx-audio-io
Project-URL: Issues, https://github.com/ssmall256/mlx-audio-io/issues
Requires-Python: >=3.10
Requires-Dist: mlx>=0.32.0; platform_system == "Darwin"
Requires-Dist: mlx[cpu]>=0.32.0; platform_system == "Linux"
Provides-Extra: dev
Requires-Dist: pytest>=9.0.2; extra == "dev"
Requires-Dist: numpy; extra == "dev"
Provides-Extra: benchmark
Requires-Dist: librosa; extra == "benchmark"
Requires-Dist: soundfile; extra == "benchmark"
Requires-Dist: numpy; extra == "benchmark"
Requires-Dist: psutil; extra == "benchmark"
Requires-Dist: torch; extra == "benchmark"
Requires-Dist: torchaudio; extra == "benchmark"
Requires-Dist: torchcodec; (platform_system != "Linux" or (platform_machine != "aarch64" and platform_machine != "arm64")) and extra == "benchmark"
Description-Content-Type: text/markdown

# mlx-audio-io

The native audio data layer for [Apple MLX](https://github.com/ml-explore/mlx): fast file decode and encode directly to and from `mlx.core.array`, with one unified API across macOS and Linux.

- **Zero-Copy MLX Pipeline**: Direct decode and encode via DLPack capsules (`mx.from_dlpack`) and the Python buffer protocol.
- **Zero Torch, Zero NumPy**: MLX is the sole required runtime dependency. No heavyweight PyTorch or NumPy runtime overhead.
- **Apple Silicon Optimized**: Native macOS backend powered by Apple AudioToolbox loads a WAV **6.8x faster** than librosa and saves one **1.5x faster** than SoundFile on an M4 Max ([measurements](#performance-highlights)).
- **Decoupled Architecture**: Upgrading `mlx` never requires rebuilding `mlx-audio-io`. One build works with any installed MLX (0.32.0+).
- **Concurrent Writer Engine**: Staged buffer preparation (`prepare_save` / `save_prepared`) releases the Python GIL and avoids MLX contention across background export workers.

---

## Installation

```bash
pip install mlx-audio-io
```

Prebuilt wheels are published for macOS 14 or later on Apple Silicon (Python
3.10 to 3.14), so nothing is compiled there. Other platforms build from source
during install; see the
[Installation Guide](docs/installation_and_troubleshooting.md) for the compiler
and Linux packages that needs.

### MLX Compatibility
`mlx-audio-io` requires:
- **macOS**: `mlx>=0.32.0` (Apple Silicon)
- **Linux**: `mlx[cpu]>=0.32.0`

Because decoded audio enters MLX via DLPack and save operations consume arrays through the buffer protocol, `mlx-audio-io` does not link against `libmlx.dylib`. Upgrading MLX versions in your environment does not require rebuilding `mlx-audio-io`.

*For Linux build dependencies, source checkout, and troubleshooting, see the [Installation Guide](docs/installation_and_troubleshooting.md).*

---

## Quickstart

### 1. Load Audio

```python
import mlx_audio_io as audio_io

# Decode native format directly into an mx.array: [frames, channels]
audio, sr = audio_io.load("speech.wav")

# Load with automatic high-quality resampling and mono fold-down
audio_16k, sr_16k = audio_io.load("speech.wav", sr=16000, mono=True)
```

### 2. Save Audio

```python
# Save float32 or pcm16 WAV
audio_io.save("out.wav", audio, sr)
audio_io.save("out_pcm16.wav", audio, sr, encoding="pcm16")

# Save compressed formats (MP3, AAC/M4A, FLAC)
audio_io.save("out.mp3", audio, sr, bitrate="192k")
audio_io.save("out.m4a", audio, sr, bitrate="256k")
audio_io.save("out.flac", audio, sr)
```

### 3. Chunked Streaming

Stream long audio files in fixed-duration chunks without decoding the whole file into RAM:

```python
for chunk, chunk_sr in audio_io.stream("long_recording.wav", chunk_duration=2.0):
    # chunk is an mx.array of shape [frames, channels]
    process(chunk)
```

### 4. Concurrent Background Export

For multi-stem export pipelines (e.g. Demucs, audio separators), stage the buffer once on the producer thread and delegate writing to background file workers:

```python
from concurrent.futures import ThreadPoolExecutor
import mlx_audio_io as audio_io

# Producer: stage read-only view and evaluate lazy MLX graph
prepared = audio_io.prepare_save(stem, layout="channels_first")

# Worker threads: encode and write without holding the Python GIL
with ThreadPoolExecutor(max_workers=4) as workers:
    workers.submit(audio_io.save_prepared, "vocals.wav", prepared, 44100, encoding="pcm16")
```

### 5. Fast Metadata Inspection

Read container metadata in microseconds without reading or decoding sample frames:

```python
meta = audio_io.info("speech.wav")
print(meta.duration, meta.sample_rate, meta.channels, meta.subtype)
```

---

## API Overview

| Function / Class | Description | Documentation |
|---|---|---|
| [`load`](docs/api_reference.md#load) | Decode audio file to `mx.array` with optional resampling, slicing, and mono mix | [Details](docs/api_reference.md#load) |
| [`save`](docs/api_reference.md#save) | Write `mx.array` or buffer-compatible array to WAV, MP3, M4A, FLAC, AIFF | [Details](docs/api_reference.md#save) |
| [`prepare_save`](docs/api_reference.md#prepare_save) | Stage evaluated buffer view on producer for concurrent export threads | [Details](docs/api_reference.md#prepare_save) |
| [`save_prepared`](docs/api_reference.md#save_prepared) | File encoder for background worker threads (releases the GIL while encoding) | [Details](docs/api_reference.md#save_prepared) |
| [`PreparedAudio`](docs/api_reference.md#preparedaudio) | Read-only audio buffer wrapper preserving strides and memory layout | [Details](docs/api_reference.md#preparedaudio) |
| [`stream`](docs/api_reference.md#stream) | Generator yielding fixed-frame or fixed-duration `mx.array` chunks | [Details](docs/api_reference.md#stream) |
| [`info`](docs/api_reference.md#info) | Fast header inspection returning `AudioInfo` (frames, duration, channels) | [Details](docs/api_reference.md#info) |
| [`batch_load`](docs/api_reference.md#batch_load) | Multi-threaded multi-file audio decoding into a list of `mx.array` | [Details](docs/api_reference.md#batch_load) |
| [`supports_soxr`](docs/api_reference.md#supports_soxr) | Check whether high-quality `libsoxr` resampling support is enabled | [Details](docs/api_reference.md#supports_soxr) |

*For complete signatures and parameter contracts, see the [Full API Reference](docs/api_reference.md).*

---

## Platform Backends

| Capability | macOS Backend | Linux Backend |
|---|---|---|
| **Engine** | Apple AudioToolbox | Native C++ WAV/MP3 + `libav` (FFmpeg) |
| **Supported Formats** | WAV, MP3, M4A/AAC, FLAC, AIFF, CAF | WAV, MP3, FLAC, M4A/AAC, AIFF, CAF |
| **Encodings** | `float32`, `pcm16`, `alac` (lossless M4A) | `float32`, `pcm16`, `alac` (lossless M4A) |
| **Resampling** | AudioToolbox (`best`) / `libsoxr` (`soxr_vhq`) | Native linear / `libav` / `libsoxr` |
| **Streaming** | Full chunked streaming across all formats | Full chunked streaming across all formats |

---

## Performance Highlights

Measured on Apple M4 Max (macOS 27.0) on a 194.8-second stereo 44.1 kHz PCM16 WAV track (median p50 latency):

| Operation | macOS M4 Max | vs librosa / soundfile | vs torchaudio |
|---|---|---|---|
| **Full WAV Load** | **3.74 ms** | **6.8x faster** than librosa | **9.2x faster** |
| **WAV Partial Read (1s)** | **0.05 ms** | **3.4x faster** than librosa | **708x faster** |
| **MP3 Load (native SR)** | **37.88 ms** | **1.1x faster** than librosa | **1.9x faster** |
| **WAV Save (Float32)** | **14.07 ms** | **1.5x faster** than SoundFile | **1.5x faster** |
| **Save Prepared (`save_prepared`)** | **13.77 ms** | **1.5x faster** than SoundFile | **1.6x faster** |
| **Load + Resample (16 kHz, `fastest`)** | **10.76 ms** | **5.6x faster** than librosa | **5.0x faster** |
| **Load + Resample (16 kHz, `best`)** | **33.17 ms** | **1.8x faster** than librosa | **1.6x faster** |

*For complete benchmarking methodology, Linux arm64/x86_64 numbers, and tail latency profiles, see [Benchmarking & Performance](docs/benchmarking.md).*

---

## Documentation

- 📖 [**API Reference**](docs/api_reference.md) — Comprehensive signatures, parameters, and return types for all functions.
- ⚡ [**Benchmarking & Performance**](docs/benchmarking.md) — Detailed latency tables, methodology, and cross-framework comparisons.
- 🛠️ [**Installation, Builds & Troubleshooting**](docs/installation_and_troubleshooting.md) — Linux libav dependencies, wheel repair, Docker workflows, and diagnostic tools.

---

## License

MIT
