macOS · Core edition · v0.9.7 · GPL-3.0

The shortest
deterministic path
from file to DAC.

bpplay is a minimalist, bit-perfect music player for macOS. One C file, about two thousand lines, no external dependencies. It has a single job: deliver the samples of a music file to your DAC untouched — no resampling, no software volume, no mixing.

FILE HOG MODE FORMAT MATCH LOAD + MLOCK MEMCPY → DAC
Free, open source, and short enough to read end to end.
The detour most players take

Software gets between
the file and the DAC.

On an ordinary macOS app, audio doesn't reach the DAC directly — it passes through CoreAudio's system mixer, where resampling, floating-point mixing and software volume can all quietly change the signal.

Typical player
  • 1 Decode file
  • 2 System mixer (CoreAudio)
  • 3 Resample to mixer rate
  • 4 Float32 mixing + software volume
  • 5 Buffer, re-buffer, dither
  • 6 DAC
bpplay
  • 1 Decode file, once, before playback
  • 2 Hog mode — exclusive DAC ownership
  • 3 DAC
Architecture

Four steps, each run once,
all finished before playback starts.

Everything that could touch the signal happens before the DAC is running. During playback there is exactly one operation left.

1

Device acquisition

hog mode — bpplay becomes the sole owner of the DAC. No other app can interfere; the system mixer is disabled.

2

Format negotiation

bpplay asks the hardware for an integer physical format. If the device only offers float32, it takes that instead — and tells you which route it took.

3

Load & match

The whole file is read into memory. If a lossless format conversion is needed, it happens once here, on a non-real-time thread.

4

mlock

The decoded buffer is pinned in RAM. The operating system cannot page it out mid-playback.

During playback, the real-time IOProc does exactly one thing: memcpy. No float math, no allocation, no file reads, no locks — the callback that feeds your DAC never does anything a real-time thread shouldn't.
The full-RAM model

The whole track loads
before a single sound plays.

No on-the-fly buffering, no disk reads during playback. The track sits in RAM, locked there, and reaches the DAC with a single memory copy.

This also has an electrical rationale, not just a signal-path one. A conventional player continuously reads, decodes and re-buffers — each operation is a brief, spiky load on the machine's power supply. A modern NVMe SSD's read spike can jump from 15 mA to 2 A in microseconds, a di/dt of nearly two million amps per second, a real source of high-frequency EMI. Once the track is fully in RAM, none of that happens during playback — there's nothing left to spike.

0
Disk reads during playback
15mA→2A
Typical NVMe read spike
~2M A/s
di/dt of that spike
1
Operation in the real-time path
4 GB DSD256 file × 1.5 (DoP packing) × 1.333 (float32 path) = ~7.5 GB in RAM

Neither step is lossy. The float32 mantissa is 24 bits, so the 16/24-bit integer range fits inside it exactly — the extra memory is the honest cost of two lossless conversions, not waste.

DoP & DSD

DSD, carried inside PCM,
bit-for-bit.

DSD256 stores the signal as 1-bit samples at 11.2896 MHz per channel — too dense for USB audio to carry directly. bpplay packs it into PCM using the DoP (DSD over PCM v1.1) protocol.

8 bits
16 bits of raw DSD, bit-for-bit identical to the .dsf file
Marker: alternates 0x05 / 0xFA
The DSD payload — untouched

The alternating marker is a self-checking handshake: a DAC that understands DoP unpacks the bits into its own DSD decoder; one that doesn't just plays it as plain PCM and stays passive. Either way, the DoP frame is only the transport — never the content. Validated up to DSD256, architecture scales to DSD512.

Formats

What it plays —
and what it deliberately doesn't.

FormatDetails
WAV16 / 24 / 32-bit integer and 32-bit float
FLAC16 / 24-bit, Vorbis metadata, MQA detection (not decoding)
ALAC (M4A)16 / 24-bit — what iTunes / Music.app produce
AIFF / AIFC16 / 24 / 32-bit, uncompressed only
DSF (DSD)DSD64–DSD256 via DoP

bpplay plays files — from local storage, a NAS, or a Google Drive / Dropbox folder, as long as it's mounted on the Mac. It is not a streaming client: no built-in connection to Spotify, Tidal, Qobuz or similar services.

Deliberately out of scope

Library management, a graphical interface, network streaming, signal processing, volume control. None are oversights — each would be a place where the signal could change, or noise could arise, between the file and the DAC.

See it

Install and play,
in under two minutes.

A short, unedited screen recording of installing bpplay and playing an album — start to finish.

bpplay-install-demo.mp4 · 1:20 · macOS 27
Validated, not assumed

Tested where it matters:
the connection.

Bit-perfect behaviour was identical across every topology and cable tried — the bit path is independent of how you connect it.

Get started

Terminal, or drag-and-drop.
Your choice.

The DMG bundles the CLI binary plus two zero-configuration launchers — a drag-and-drop app and a Finder Quick Action. Both are Developer ID signed and notarised.

$ ./bpplay -l # list available output devices $ ./bpplay -d 1 track.flac # play on device index 1 $ ./bpplay -d 1 01.flac 02.flac # gapless across same-format files $ ./bpplay -d 1 -dir ~/Music/Album # play a whole folder, recursively while playing — n next · b previous · space pause/resume · q quit
Requires macOS 10.15+ and at least 8 GB RAM (more for large DSD albums — see the memory math above).
"bpplay forgoes a polished interface and convenience features, and in return gives a reference — a fixed point to measure against."
From the project's design philosophy