Releases: M-Igashi/baken
Release list
v3.0.1
Bake'n Deck 3.0.1 — faster lossless gain via mp3rgain 2.10
Highlights
- Updated built-in mp3rgain library from 2.9.6 to 2.10.0. The gain-apply pipeline now reads each file once instead of twice, roughly halving I/O on large batches, and APE tag-only updates rewrite just the file tail. Output stays bit-identical — this is a pure performance update, no behavior changes.
Other Changes
- Deduplicated the shared interactive/scriptable pipeline in
cli.rs - Codebase simplification: deduplicated XML helpers, fixed a potential panic on non-ASCII paths, misc cleanups
- Added
homepageto crate metadata (now live on crates.io) - Excluded
web/from the crates.io package
Full Changelog: v3.0.0...v3.0.1
v3.0.0
Bake'n Deck 3.0.0 — headroom is now baken
headroom is now Bake'n Deck (issue #60). The binary, crate, Homebrew formula, and repository are renamed to baken, the CLI moves to a subcommand layout, and a third subcommand — cdjsafe — completes the Rekordbox → CDJ prep toolkit: loudness gain, Key+BPM playlist sort, and CDJ-safe MP3 transcode, all baked into the files so they survive USB export.
Highlights
- Rebrand: headroom → Bake'n Deck (
baken) (#60). New install channels:brew install M-Igashi/tap/baken,winget install M-Igashi.baken,cargo install baken,yay -S baken-bin. Website moves to baken.ravers.workers.dev. This is a hard cut — the oldheadroomchannels stop receiving updates (pre-announced in #61). - Subcommand CLI. The loudness analyzer now lives under
baken headroom; the playlist sorter stays atbaken rbsort. Barebakenprints help. All analyzer flags and both interactive/scriptable modes are unchanged, just one level deeper. - New:
baken cdjsafe(#40). Emergency-backup USB prep for pre-NXS2 CDJs: converts every track in a Rekordbox playlist to 320 kbps CBR MP3 @ 44.1 kHz (ID3v2.3, artwork kept) and emits an updated XML in which each new track inherits the source's beatgrid and hot/memory cues verbatim — import, "Import to Collection", export to USB, no re-analysis. Sources already at the safe profile are copied byte-identically; lossy→lossy re-encodes are listed in the run report.
Other changes
- CSV report default filename is now
baken_report_<timestamp>.csv. - Update-check opt-out env var renamed:
HEADROOM_NO_UPDATE_CHECK→BAKEN_NO_UPDATE_CHECK. - Backup directories are marked with
.baken-backup; directories with the legacy.headroom-backupmarker are still skipped, so existing v2 backups are never re-processed. - Cargo metadata refreshed: description and keywords now reflect the DJ/Rekordbox/CDJ scope.
- Docs and release workflow rebranded; the Homebrew formula published by CI is now
Formula/baken.rb.
Migration
Reinstall via the new baken packages — the old headroom install channels no longer receive updates:
| Old | New |
|---|---|
brew install M-Igashi/tap/headroom |
brew install M-Igashi/tap/baken |
winget install M-Igashi.headroom |
winget install M-Igashi.baken |
cargo install headroom |
cargo install baken |
yay -S headroom-bin |
yay -S baken-bin |
headroom [paths] [flags] |
baken headroom [paths] [flags] |
headroom rbsort ... |
baken rbsort ... |
HEADROOM_NO_UPDATE_CHECK |
BAKEN_NO_UPDATE_CHECK |
Scripts calling the old bare headroom command must switch to baken headroom; flags are unchanged.
v2.1.1
headroom 2.1.1 — rbsort performance & maintenance
A small maintenance release. rbsort XML parsing is faster, and the dependency and CI toolchains are refreshed. No new flags, no behavior changes: output is byte-identical to 2.1.0.
Performance
- Faster rbsort XML parsing (#56). Both the scan and rewrite passes now read events directly from the in-memory XML slice (quick-xml's zero-copy slice reader) instead of copying each event through an intermediate buffer, and the rewrite pass writes borrowed events instead of deep-copying them. The collection map is also pre-sized from the
COLLECTION Entriesattribute. ~10% faster on a 50k-track (32 MB) collection export, with byte-identical output.
Other changes
- Dependencies: quick-xml 0.40 → 0.41, mp3rgain 2.8.0 → 2.9.4, plus routine
rust-minor-patchgroup updates (serde, serde_json, chrono, clap, …). - CI: actions/checkout v6 → v7, dtolnay/rust-toolchain refreshed, softprops/action-gh-release 3.0.0 → 3.0.1.
Migration
None. Fully backward-compatible with v2.1.0.
v2.1.0
headroom 2.1.0 — AI-assisted hardening & performance
A reliability and performance release. The codebase was systematically audited with Claude (Fable 5), which uncovered several latent bugs — including one that could silently modify your backups — all fixed here, alongside a round of performance work. No new flags, no breaking changes: existing commands behave the same, just safer and faster.
Latent bugs found & fixed (Claude Fable 5 audit)
- Backups are no longer re-processed (#45). The default backup directory
<target>/backuplives inside the scan root, so a second run would pick the backup copies up and gain-adjust them too — defeating the purpose of a backup. Backup directories created by headroom now contain a.headroom-backupmarker file and are skipped during recursive scans. Explicitly pointing headroom at a backup directory still works. Note: backups created by older versions are unmarked; re-running with--backupmarks the default location going forward. - Silent audio no longer saturates the gain math. ffmpeg's loudnorm reports
-inffor silent files, which previously overflowed intoi32::MAXgain steps. Non-finite measurements are now rejected with a clear per-file error. - Backup path edge case. With mixed-root inputs,
strip_prefixcould yield an absolute or empty relative path, making the backup copy target the source file itself. Now guarded with a bare-filename fallback. - Report column alignment. Columns are padded before ANSI styles are applied, fixing misaligned analysis tables.
Performance
- Parallel gain processing. File processing now runs in parallel via rayon (analysis already did), cutting wall-clock time on multi-file batches.
- One less process per lossy file (#47). The bitrate is parsed from the loudnorm run's existing ffmpeg output instead of spawning a separate ffprobe for every MP3/AAC file; ffprobe remains as a fallback.
- Startup is never blocked by the update check (#46). The version check runs on a background thread with a 3-second timeout, and the upgrade hint now prints after the run — where you'll actually see it.
Other changes
- Refactor: per-format gain wrappers merged into a single
LossyFormatenum - Docs: rbsort sort-comparison write-up (
docs/rbsort-sort-comparison.md), README updates - Dependencies: mp3rgain 2.7.0 → 2.8.0, chrono 0.4.45, serde_json bump
- CI: actions/checkout pinned to v6.0.3
Migration
None. Fully backward-compatible with v2.0.x.
v2.0.0
headroom 2.0.0 — rbsort ships
This is the first major-version bump since the project began. headroom is no longer just a loudness analyzer: it now has a CLI subcommand surface, and the inaugural subcommand rbsort ships in this release.
All v1.x loudness behaviour is 100% backward-compatible — headroom <paths> and bare-invocation interactive mode are unchanged.
Headliner: rbsort — Rekordbox playlist sorter for harmonic mixing
A pure XML-in / XML-out workflow. Takes a Rekordbox collection.xml export and produces a key/tempo-sorted copy ready to re-import. No audio is touched, no database is written, ffmpeg is not required.
What it does
Sorts a target playlist — or every TrackID-referenced playlist in the XML — by:
- Camelot Key ascending (
1A→1B→2A→ … →12B) - BPM ascending within each key group
Sorted copies are written into a brand-new Sorted (Key+BPM)/ folder appended to the ROOT node, each playlist keeping its source name. Mirrors the analyzer's existing backup/ directory pattern.
Tracks with no Camelot key sort after all known keys; within a key group, tracks with no/0 BPM sort last.
Usage
# Sort *every* TrackID-referenced playlist in one pass (recommended)
headroom rbsort --xml /path/to/collection.xml
# Sort a single playlist with a custom name
headroom rbsort \
--xml /path/to/collection.xml \
--playlist "Folder/MyPlaylist" \
--output sorted.xml \
--name "MyPlaylist (Camelot+BPM)"Defaults:
| Flag | Behaviour when omitted |
|---|---|
--output |
<input-stem>-out.<ext> next to the input (e.g. coll.xml → coll-out.xml) |
--playlist |
Sort every TrackID-referenced (KeyType="0") playlist in the XML |
Rekordbox workflow
- Preferences > View > Key display format → Alphanumeric so
Tonalityexports as Camelot (1A..12B). Non-Camelot tonalities silently sort last. - File > Export Collection in xml format →
collection.xml. - Run
headroom rbsort --xml collection.xml. - Preferences > Advanced > Database > rekordbox xml → Imported Library points at the output XML; restart Rekordbox.
- Open the rekordbox xml tree in the left sidebar; drag the sorted playlist into your real Playlists tree, or right-click → Export Playlist for CDJ EXPORT mode.
Implementation highlights
- New module
src/rbsort/(mod,camelot,xml) on top ofquick-xml0.40. - Two-pass design: scan
COLLECTION+ target playlists, then stream-rewrite with the sorted folder injected inside<PLAYLISTS>before the ROOT</NODE>closes. ROOTCountis bumped by 1. - Robust against real Rekordbox exports —
<TRACK>elements with nested<TEMPO>/<POSITION_MARK>children are handled correctly (the originalEvent::Empty-only path produced an empty collection map and a no-op sort). - Subcommand dispatch short-circuits before the audio pipeline, the banner, ffmpeg check, and the update check —
rbsortruns in milliseconds and has zero audio-stack dependencies. - Verified end-to-end on a real 5,255-track / 24-playlist Rekordbox export — sorted in under a second with zero ordering violations.
Why a major version?
Until now, headroom only did one thing: audio loudness analysis and gain adjustment. v2.0.0 introduces a subcommand surface to the CLI, and rbsort is the first to land there. Future non-audio DJ-prep workflows (set planning, transition analysis, etc.) will be added as subcommands too.
Existing flows are untouched:
headroom→ interactive loudness analyzer (unchanged)headroom <paths> [flags]→ scriptable loudness analyzer (unchanged)headroom rbsort ...→ new Rekordbox playlist sorter
Internal
- XML scanner/rewriter switched to byte-level element-name comparison and single-pass attribute extraction — fewer allocations on large exports.
Option<T>"None-last" ordering extracted into a reusable helper.processor.rsinternal helpers tightened frompubto private; deadAnalysisSummary::total()removed.default_output_pathsimplified to usePath::with_file_name.- 19 unit tests, including full XML round-trip with multi-playlist nested folders.
Migration
None. The audio side is wire-compatible with v1.x. rbsort is purely additive.
v1.10.1
Highlights
- mp3rgain 2.6.1: Upgrade to the stable
symphonia 0.6.0release (previously0.6.0-alpha.2). No public API changes; lossless MP3/AAC gain behavior is identical.
Other Changes
- ci: bump actions/dependency-review-action from 4.9.0 to 5.0.0 (#36)
Highlights
- Uniform True Peak ceiling at -0.5 dBTP, with full per-run tuning. AES TD1008's bitrate-dependent ceiling describes the limiter threshold prior to lossy encoding (§7B Sources of Peak Overshoot — Codecs). headroom processes already-encoded delivery files, where there is no further codec stage downstream to absorb additional overshoot, so the same -0.5 dBTP ceiling — the most aggressive value TD1008 sanctions for any limiter in the chain — is now applied uniformly to every file. Low-bitrate lossy files gain +0.5 dB of loudness for free; lossless and ≥256 kbps lossy behaviour is unchanged. Resolves #34.
- New
--tp-target <DB>flag. Override the uniform target with any custom value, e.g.--tp-target -1.0for the Spotify / Apple Music / YouTube delivery max, or--tp-target -2.0for a conservative master that leaves headroom for player-side SRC / Hilbert downmix. - New
--tp-split-bitrateflag. Opt back into the legacy bitrate-dependent split (-0.5 dBTP for ≥256 kbps, -1.0 dBTP for <256 kbps). Mirrors TD1008's pre-encode interpretation for users who prefer it. - Native-lossless threshold scales with the chosen target. The True Peak below which an MP3/AAC file qualifies for in-place global_gain modification is now
target − 1.5 dBrather than the hardcoded -2.0 / -2.5 dBTP used through v1.9.x. - mp3rgain bumped to v2.5.0. Brings a fix for temp-file collisions when applying gain in parallel (mp3rgain@4e9b0b3) — relevant because headroom applies gain across files in parallel via rayon. Also picks up faster AAC apply / ReplayGain analysis pipelines.
Documentation
- New docs/true-peak-ceiling.md walks through the TD1008 reading with §-level citations, explains the pre-encode vs delivery distinction, and lists preset flag combinations for common targets (Spotify / R128 / TD1008 §4 / TD1008 §7B).
- README §True Peak Ceiling rewritten end-to-end with the new flag table and migration note.
Migration
Users who relied on the v1.9.x bitrate-dependent split can restore it exactly with --tp-split-bitrate. Users who want to match streaming-platform delivery max can use --tp-target -1.0.
v1.10.0
Highlights
- Uniform True Peak ceiling at -0.5 dBTP, with full per-run tuning. AES TD1008's bitrate-dependent ceiling describes the limiter threshold prior to lossy encoding (§7B Sources of Peak Overshoot — Codecs). headroom processes already-encoded delivery files, where there is no further codec stage downstream to absorb additional overshoot, so the same -0.5 dBTP ceiling — the most aggressive value TD1008 sanctions for any limiter in the chain — is now applied uniformly to every file. Low-bitrate lossy files gain +0.5 dB of loudness for free; lossless and ≥256 kbps lossy behaviour is unchanged. Resolves #34.
- New
--tp-target <DB>flag. Override the uniform target with any custom value, e.g.--tp-target -1.0for the Spotify / Apple Music / YouTube delivery max, or--tp-target -2.0for a conservative master that leaves headroom for player-side SRC / Hilbert downmix. - New
--tp-split-bitrateflag. Opt back into the legacy bitrate-dependent split (-0.5 dBTP for ≥256 kbps, -1.0 dBTP for <256 kbps). Mirrors TD1008's pre-encode interpretation for users who prefer it. - Native-lossless threshold scales with the chosen target. The True Peak below which an MP3/AAC file qualifies for in-place global_gain modification is now
target − 1.5 dBrather than the hardcoded -2.0 / -2.5 dBTP used through v1.9.x. - mp3rgain bumped to v2.5.0. Brings a fix for temp-file collisions when applying gain in parallel (mp3rgain@4e9b0b3) — relevant because headroom applies gain across files in parallel via rayon. Also picks up faster AAC apply / ReplayGain analysis pipelines.
Documentation
- New docs/true-peak-ceiling.md walks through the TD1008 reading with §-level citations, explains the pre-encode vs delivery distinction, and lists preset flag combinations for common targets (Spotify / R128 / TD1008 §4 / TD1008 §7B).
- README §True Peak Ceiling rewritten end-to-end with the new flag table and migration note.
Migration
Users who relied on the v1.9.x bitrate-dependent split can restore it exactly with --tp-split-bitrate. Users who want to match streaming-platform delivery max can use --tp-target -1.0.
v1.9.0
Highlights
- Update notification on startup. headroom now checks GitHub Releases once per 24 hours and prints the appropriate upgrade command (Homebrew / winget / cargo) when a newer version is available. Disable with
--no-update-checkorHEADROOM_NO_UPDATE_CHECK=1. - Reliable AAC/M4A gain via mp3rgain v2.3.0. Picks up mp3rgain#120 which fixes a short-window spectral parser bug that previously caused some processed
.m4afiles to fail in ffmpeg withinvalid band type/Number of bands exceeds limit. Also benefits from mp3rgain#121 — AAC analysis is now 4-6× faster.
Other Changes
- deps: bump rayon and the rust-minor-patch group (#33)
v1.8.0
Installation
| Platform | Command |
|---|---|
| macOS (Homebrew) | brew install M-Igashi/tap/headroom |
| Windows (winget) | winget install M-Igashi.headroom |
| Cargo | cargo install headroom (ffmpeg must be installed separately) |
Package managers (Homebrew, winget) install ffmpeg automatically. mp3rgain is built-in — no separate installation needed.
Checksums
See headroom-v1.8.0-checksums.txt for SHA256 checksums of all binaries.
What's Changed
- ci: bump softprops/action-gh-release from 2.6.1 to 3.0.0 by @dependabot[bot] in #30
- ci: bump actions/upload-artifact from 7.0.0 to 7.0.1 by @dependabot[bot] in #31
- feat: add CLI flags for scriptable, non-interactive usage (#29) by @M-Igashi in #32
Full Changelog: v1.7.3...v1.8.0
v1.7.3
Installation
| Platform | Command |
|---|---|
| macOS (Homebrew) | brew install M-Igashi/tap/headroom |
| Windows (winget) | winget install M-Igashi.headroom |
| Cargo | cargo install headroom (ffmpeg must be installed separately) |
Package managers (Homebrew, winget) install ffmpeg automatically. mp3rgain is built-in — no separate installation needed.
Checksums
See headroom-v1.7.3-checksums.txt for SHA256 checksums of all binaries.
What's Changed
- chore(ci): add dependency review and fix context injection in run blocks by @M-Igashi in #27
- ci: bump dtolnay/rust-toolchain from efa25f7f19611383d5b0ccf2d1c8914531636bf9 to 3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 by @dependabot[bot] in #28
Full Changelog: v1.7.2...v1.7.3