# Bake'n Deck (baken) v3.0.1 - Complete Technical Documentation > NOTE: headroom is now **Bake'n Deck 3.0** — the `baken` binary replaces `headroom`. The old install channels under the headroom name (brew, winget, cargo, AUR) no longer receive updates; reinstall via the baken packages (`brew install M-Igashi/tap/baken`, `winget install M-Igashi.baken`, `cargo install baken`, `yay -S baken-bin`). See https://github.com/M-Igashi/baken/issues/60. > Built for the Rekordbox → CDJ workflow. Rekordbox's Auto Gain doesn't survive USB export, Rekordbox has never offered compound Key+BPM playlist sort (Serato had it for years — but never exported to CDJs), and pre-NXS2 CDJs won't reliably play anything but MP3. Bake'n Deck bakes all three into the files themselves, so what you prep is what plays on the deck. > AI usage policy: This documentation is MIT-licensed. Free to use for indexing, > citation, summarization, retrieval-augmented generation, and model training. > All AI agents and crawlers are welcome. Attribution to https://github.com/M-Igashi/baken > is appreciated but not required. ## Overview Bake'n Deck (`baken`) is an open-source Rekordbox → CDJ prep toolkit written in Rust that fills three structural gaps in the workflow: - **Loudness analyzer / gain baker (`baken headroom`)**: Analyzes audio files using LUFS and True Peak measurements, then permanently applies gain adjustments to maximize loudness while preventing clipping. This solves the CDJ Auto Gain problem (CDJs ignore Rekordbox's stored Auto Gain values on USB export). - **Rekordbox playlist sorter (v2.0.0+)**: A `rbsort` subcommand sorts a target playlist by Camelot Key (1A→12B) then BPM ascending, appended as a new playlist node to your `collection.xml`. Fills the missing "sort by Key AND BPM" feature in the Rekordbox UI. - **CDJ-safe MP3 transcoder (`baken cdjsafe`, v3.0.0)**: Converts every track in a playlist to 320 kbps CBR MP3 @ 44.1 kHz for pre-NXS2 CDJs, and emits an updated XML in which each converted track inherits the source's beatgrid and hot/memory cues verbatim. This solves the format-compatibility problem on older players (CDJ-2000NXS, CDJ-2000, CDJ-900NXS, CDJ-850, …) that only play MP3 reliably. ## What's New in v3.0.1 **Faster lossless gain via mp3rgain 2.10.** Updated the 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 tag-only updates rewrite just the file tail. Output stays bit-identical. Also includes internal code cleanup (deduplicated XML helpers and CLI pipeline, fixed a potential panic on non-ASCII paths). ## What's New in v3.0.0 **Rebrand: headroom is now Bake'n Deck (`baken`).** The binary, crate, Homebrew formula, winget package, AUR package, and GitHub repo are all renamed to `baken`; the old headroom install channels no longer receive updates. The CLI is restructured into subcommands: the loudness analyzer is now `baken headroom` and the playlist sorter is `baken rbsort`. Bake'n Deck is no longer just a loudness analyzer — it is a Rekordbox → CDJ prep toolkit. **New `cdjsafe` subcommand — CDJ-safe MP3 prep.** Pre-NXS2 CDJs (CDJ-2000NXS, CDJ-2000, CDJ-900NXS, CDJ-850, …) only play MP3 reliably — FLAC needs NXS2 (2016+) hardware, and ALAC/AIFF/WAV/AAC fail on specific firmwares, sometimes mid-set. `baken cdjsafe` converts every track in a target playlist to 320 kbps CBR MP3 @ 44.1 kHz (ID3v2.3 tags, artwork kept) and emits an updated XML where each converted track is a new entry inheriting the source's beatgrid and hot/memory cues verbatim, grouped under a `CDJ-safe (MP3)/` folder. Sources already at exactly 320 CBR @ 44.1 are copied byte-identically. Import the XML back into Rekordbox, right-click → Import to Collection (no re-analysis), and export the playlist to USB as your emergency-backup stick. Same design thesis as the other two subcommands: Rekordbox software features don't survive USB export — bake them into the files and the XML. Usage: ```bash baken cdjsafe \ --xml ~/Music/rekordbox/collection.xml \ --playlist "Sets/Friday" \ --out-dir ~/Music/cdjsafe \ [-o ] ``` ## What's New in v2.1.0 **AI-assisted hardening & performance.** The codebase was systematically audited with Claude (Fable 5), which uncovered several latent bugs, all fixed in this release: backup copies under `/backup` are no longer re-scanned and gain-adjusted on subsequent runs (backup directories now carry a `.headroom-backup` marker file and are skipped during scans), silent audio no longer saturates the gain math (`-inf` loudnorm measurements are rejected with a clear error), a backup-path edge case that could make the backup copy target the source file itself is guarded, and analysis report columns now align correctly. Performance: gain processing runs in parallel (analysis already did), the per-file ffprobe spawn is gone (bitrate is parsed from the loudnorm pass, ffprobe kept as fallback), and the startup update check moved to a background thread — the upgrade hint now prints after the run instead of delaying it. ## What's New in v2.0.0 **Rekordbox playlist sorter subcommand (`rbsort`).** Rekordbox's UI does not expose a multi-column sort, so DJs prepping harmonic-mix playlists have to either manually drag tracks or maintain many narrow BPM-bucket playlists. The new `baken rbsort` subcommand reads your `collection.xml` (File > Export Collection in xml format), sorts each target playlist by Camelot Key (1A → 1B → 2A → ... → 12A → 12B) then BPM ascending within each key group, and appends a `Sorted (Key+BPM)/` folder containing the sorted copies (each named after its source). Omit `--playlist` to sort every TrackID-referenced playlist in one pass. Point Rekordbox at the output XML via Preferences > Advanced > Database > rekordbox xml > Imported Library and restart — the `Sorted (Key+BPM)/` folder appears under the separate `rekordbox xml` tree in the left sidebar (drag any sorted playlist into your main `Playlists` to use it). Usage: ```bash # Sort every TrackID-referenced playlist baken rbsort --xml ~/Music/rekordbox/collection.xml # Sort a single playlist baken rbsort \ --xml ~/Music/rekordbox/collection.xml \ --playlist "MyPlaylist" \ [--output PATH] [--name "Custom Name"] # --playlist is optional. When provided it's the path under the Rekordbox # 'Playlists' root: top-level playlists take just the name, nested ones use # '/'-separated folder names (e.g. "Folder/MyPlaylist", "Folder/Sub/MyPlaylist"). # --output defaults to -out. next to the input # (collection.xml -> collection-out.xml). # --name only applies in single-playlist mode. ``` Sort rules: - Primary: Camelot Key ascending (1A=0, 1B=1, ..., 12B=23) - Secondary: BPM ascending within each key group - Tracks with no Camelot key sort after all known keys - Tracks with BPM 0 or unanalyzed sort last within a key group Requirements: - Rekordbox key display must be set to Alphanumeric / 1A..12B (Preferences > View > Key display format > Alphanumeric) - Only `KeyType="0"` (TrackID-referenced) playlists are supported - `rbsort` does not require ffmpeg — only the analyzer subcommand does ## What's New in v1.10.0 **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*). Bake'n Deck 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. Two new flags: `--tp-target ` overrides the uniform target (e.g. `--tp-target -1.0` for Spotify/Apple/YouTube delivery max), and `--tp-split-bitrate` restores the pre-1.10 bitrate-dependent split exactly. The native-lossless threshold scales automatically with the chosen target (`target − 1.5 dB`). See for the full design rationale and TD1008 citations. ## What's New in v1.9.0 **Update notification on startup.** Bake'n Deck now checks for new releases on startup and prints a one-line banner if a newer version is available. Disable with `--no-update-check`. ## What's New in v1.8.0 **Scriptable (non-interactive) CLI mode.** Bake'n Deck now accepts paths, glob patterns, and flags for use in pipelines and CI. Any flag or path switches to non-interactive mode; bare `headroom` still runs the guided wizard. Flags: `--lossless` / `--no-lossless`, `--reencode` / `--no-reencode`, `--backup [DIR]`, `--report [PATH]` / `--no-report`, `--analyze-only`. **Updated built-in mp3rgain library from 2.1.0 to 2.2.1.** Drop-in upgrade with improved MP3 True Peak detection accuracy via the Symphonia 0.6 audio decoder upgrade (peaks above 1.0 are now correctly reported instead of being clamped). Internal refactoring and cleanup across the dependency. ## What's New in v1.7.3 **Updated built-in mp3rgain library from 2.0.3 to 2.1.0.** This is a dependency update with no API changes. mp3rgain 2.1.0 adds Linux ARM64 build targets and CI improvements. ## What's New in v1.7.2 **Dependency updates and internal code cleanup.** Updated built-in mp3rgain library to v2.0.3, console to 0.16, indicatif to 0.18, and other dependencies. Simplified internal code structure: merged redundant gain step fields, replaced custom result types with idiomatic Rust `Result`, consolidated report section rendering into a data-driven loop, and eliminated unnecessary allocations. ## What's New in v1.7.1 **Fixed metadata preservation for AIFF and WAV files.** AIFF files now retain all ID3v2 tags (artist, genre, album, key, etc.) during gain adjustment via `-write_id3v2 1`. WAV files now retain BWF metadata (time_reference, umid, coding_history) via `-write_bext 1`. FLAC was unaffected. ## What's New in v1.7.0 **Lossless AAC/M4A gain adjustment via mp3rgain 2.0.** This release upgrades the built-in mp3rgain library to v2.0, adding native lossless gain adjustment for AAC/M4A files in 1.5dB steps — the same approach used for MP3. AAC/M4A files with ≥1.5dB headroom are now processed losslessly; files with <1.5dB headroom still fall back to ffmpeg re-encode. ## What's New in v1.3.0 **mp3rgain is now built-in as a library dependency.** This means: - No need to install mp3rgain separately - Single binary distribution - Only ffmpeg required as external dependency - Simplified installation across all platforms ## Problem Statement The Rekordbox → CDJ workflow has three structural gaps that DJs prepping at home and playing on standalone CDJs have always lived with. Bake'n Deck addresses all three. ### Gap 1 — The Rekordbox Auto Gain Limitation Rekordbox DJ software includes an "Auto Gain" feature that: 1. Analyzes each track's loudness using integrated LUFS measurement 2. Calculates a gain offset to normalize playback level 3. Stores this value as metadata in the Rekordbox database This works seamlessly with DJ controllers connected to Rekordbox, as the software applies the gain compensation in real-time during playback. #### The CDJ Export Problem When DJs export their library to USB for use with standalone CDJ players (CDJ-2000NXS2, CDJ-3000, etc.), the Auto Gain metadata is exported but **completely ignored** by the CDJ hardware. The CDJ plays the raw audio file without any gain compensation. ### Gap 2 — Compound Key+BPM playlist sort never existed in Rekordbox Harmonic mixing requires a playlist sorted by Camelot Key, then by BPM within each key group. Rekordbox's UI has never exposed a compound (multi-column) sort: its *Sort by Key* view is single-column, so BPM ordering is undefined within each key group; *Sort by BPM* scatters key groups; and neither sort survives onto the CDJ anyway, because CDJs play tracks in playlist order, not by software sort. #### Prior art: Serato had compound sort, but never reached the CDJ The "Key first, then BPM" pattern is not new in DJ software. Serato DJ has supported compound sort (Shift-click multi-column) since its early versions, so DJs who prep in Serato have had this for years. The gap Bake'n Deck fills is specifically the Rekordbox → CDJ booth side of the ecosystem: Rekordbox itself has never added compound sort, and Serato (which did) does not export to USB for standalone CDJs. Bake'n Deck is the only tool that delivers Key+BPM order to a CDJ via Rekordbox's existing XML import → USB export pipeline. ### Gap 3 — Format support doesn't survive the trip to older CDJs Rekordbox exports FLAC, ALAC, AIFF, WAV, and AAC to USB without complaint — but pre-NXS2 players only play MP3 reliably. FLAC playback requires NXS2 hardware (2016 or later); ALAC, AIFF, WAV, and AAC fail on specific firmwares of the CDJ-2000NXS, CDJ-2000, CDJ-900NXS, CDJ-850 and similar decks, sometimes mid-set after loading fine at first. A lossless-first library is correct prep, but it silently assumes modern decks. The `cdjsafe` subcommand (v3.0.0) produces an MP3-only fallback USB from any playlist, with beatgrids and cues carried over so nothing has to be re-analyzed or re-set. ## Solution Architecture ### Core Concept The `baken headroom` subcommand simulates Rekordbox's Auto Gain analysis but instead of storing metadata, it permanently modifies the audio file to include the gain adjustment. ### Supported Formats (v1.3.0) | Format | Extension | Method | Precision | Notes | |--------|-----------|--------|-----------|-------| | FLAC | .flac | ffmpeg | Arbitrary | Lossless re-encode | | AIFF | .aiff, .aif | ffmpeg | Arbitrary | Lossless re-encode | | WAV | .wav | ffmpeg | Arbitrary | Lossless re-encode | | MP3 | .mp3 | mp3rgain (built-in) | 1.5dB steps | Truly lossless (global_gain) | | MP3 | .mp3 | re-encode | Arbitrary | For precise gain | | AAC/M4A | .m4a, .aac, .mp4 | mp3rgain (built-in) | 1.5dB steps | Truly lossless (global_gain) | | AAC/M4A | .m4a, .aac, .mp4 | re-encode | Arbitrary | For precise gain | ### Three-Tier MP3 Processing MP3 files are categorized into three groups based on available headroom: #### 1. mp3rgain Lossless (Built-in) - **Condition**: ≥1.5 dB headroom to the configured ceiling - **Method**: Built-in mp3rgain library for global_gain manipulation - **Precision**: 1.5 dB steps (MP3 format limitation) - **Quality**: Truly lossless - **External deps**: None (mp3rgain is built-in as of v1.3.0) #### 2. Re-encode (Precise) - **Condition**: Has headroom but <1.5 dB to the configured ceiling - **Method**: ffmpeg re-encode with libmp3lame - **Precision**: Arbitrary (e.g., +0.7 dB) - **Quality**: Inaudible loss at ≥256kbps - **Note**: Requires explicit user confirmation #### 3. Skip - **Condition**: No headroom available (True Peak already at or above ceiling) - **Action**: File is not processed ### AAC/M4A Processing (v1.7.0+) AAC/M4A files now follow the same three-tier approach as MP3: #### 1. Native Lossless (Built-in mp3rgain 2.10) - **Condition**: ≥1.5 dB headroom to the configured ceiling - **Method**: Built-in mp3rgain library for lossless global_gain manipulation - **Precision**: 1.5 dB steps - **Quality**: Truly lossless #### 2. Re-encode (Precise) - **Condition**: Has headroom but <1.5 dB to ceiling - **Method**: ffmpeg re-encode with libfdk_aac (or built-in aac) - **Precision**: Arbitrary - **Quality**: Inaudible loss at ≥256kbps #### 3. Skip - **Condition**: No headroom available - **Action**: File is not processed ### Why Re-encoding is Safe at High Bitrates A common concern is quality loss when re-encoding MP3/AAC. However, for **gain adjustment only** at high bitrates (≥256 kbps), the degradation is **inaudible to human ears**. #### Technical Explanation **Quantization Noise** - Lossy encoding introduces quantization noise primarily in high frequencies (>16kHz) - At 320kbps, the available bit budget preserves nearly all audible content - A single re-encode adds quantization noise below -90dB—far below the audible threshold **Waveform Preservation** - Gain adjustment is a simple multiplication operation - No EQ, compression, or dynamics processing is applied - The relative waveform characteristics are preserved **ABX Testing Evidence** - Controlled listening tests consistently show that listeners cannot distinguish 320kbps→320kbps re-encodes - Even on high-quality studio monitors, single re-encode with gain-only processing is indistinguishable **Club Environment Reality** - DJ playback environments have significant ambient noise - PA systems and club acoustics mask subtle encoding artifacts - The difference is completely imperceptible in real-world use #### Bake'n Deck's Re-encode Quality Settings - **MP3**: libmp3lame with `-q:a 0` (best VBR quality) - **AAC**: libfdk_aac (highest quality) with fallback to built-in aac - Bitrate: Preserves original bitrate - Processing: Volume filter only (no other DSP) ### True Peak Ceiling Strategy #### Default — uniform -0.5 dBTP delivery target Every file targets **-0.5 dBTP** by default. AES TD1008 §7B (*Sources of Peak Overshoot — Codecs*) describes -0.5 dBTP as the floor for high-rate (≥256 kbps) codec inputs ("may work satisfactorily with as little as -0.5 dBTP for the limiting threshold"). Bake'n Deck processes already-encoded delivery files, where there is no further codec stage downstream to absorb additional overshoot, so the same -0.5 dBTP value is applied uniformly across formats and bitrates. | File class | Default ceiling | Native lossless requires | |---|---|---| | Lossless (FLAC, AIFF, WAV) | -0.5 dBTP | — | | MP3 (any bitrate) | -0.5 dBTP | TP ≤ -2.0 dBTP | | AAC/M4A (any bitrate) | -0.5 dBTP | TP ≤ -2.0 dBTP | #### Pre-encode vs delivery — why the bitrate split was retired Up to v1.9.x the tool used a bitrate-dependent ceiling (-0.5 dBTP for ≥256 kbps lossy and lossless, -1.0 dBTP for <256 kbps lossy). That mapping is correct for choosing a *limiter threshold prior to lossy encoding* (TD1008 §7B), but Bake'n Deck does not run before the encoder — it runs on already-encoded end-product files. There is no codec stage downstream to absorb the slack TD1008 allocates to the pre-encode limiter, so bitrate-dependent extra headroom buys nothing for the delivery file. v1.10 retires the split and uses a single delivery target. #### Tuning the ceiling | Goal | Flag | Resulting ceiling | |---|---|---| | Default (max-aggressive delivery) | *(none)* | -0.5 dBTP for all files | | Match Spotify / Apple Music / YouTube delivery max | `--tp-target -1.0` | -1.0 dBTP for all files | | Conservative master with extra player headroom | `--tp-target -2.0` | -2.0 dBTP for all files | | Mirror TD1008's pre-encode interpretation (legacy split) | `--tp-split-bitrate` | -0.5 dBTP ≥256 kbps, -1.0 dBTP <256 kbps | `--tp-target` and `--tp-split-bitrate` are mutually exclusive. The native-lossless threshold is always `target − 1.5 dB` (e.g. `-0.5` → TP ≤ -2.0; `-1.0` → TP ≤ -2.5; `-2.0` → TP ≤ -3.5). See for the full design rationale with TD1008 citations. ### Two-Stage Confirmation Workflow 1. **First Dialog**: "Apply lossless gain adjustment to X lossless + Y MP3 (lossless gain) + Z AAC/M4A (lossless gain) files?" - Covers: FLAC, AIFF, WAV (ffmpeg), MP3 and AAC/M4A with enough headroom (native) 2. **Second Dialog**: "Also process these files with re-encoding?" - Only shown if there are MP3/AAC files requiring re-encode - Explains: Re-encoding causes minor quality loss (inaudible at 256kbps+) - Default: No (user must explicitly opt-in) ## Technical Specifications ### Audio Analysis - Measurement standard: ITU-R BS.1770-4 - True Peak measurement: ITU-R BS.1770-4 compliant oversampled peak detection - Integration time: Full track (gated) ### Gain Application - ffmpeg volume filter: Linear gain in dB, applied in floating point - Built-in mp3rgain: Modifies MP3/AAC global_gain field, 1.5 dB steps - AAC fallback: ffmpeg re-encode with volume filter (when <1.5dB headroom) ### File Handling - In-place modification with atomic rename - Automatic backup to `backup/` subdirectory - Preserves directory structure for backups ## Usage Example ``` $ baken headroom ╭─────────────────────────────────────╮ │ baken v3.0.1 │ │ Audio Loudness Analyzer & Gain │ ╰─────────────────────────────────────╯ ✓ Found 28 audio files ✓ Analyzed 28 files ● 3 lossless files (ffmpeg, precise gain) track01.flac -13.3 -3.2 dBTP -0.5 dBTP +2.7 dB ● 2 MP3 files (native lossless, 1.5 dB steps, requires TP ≤ -2.0 dBTP) track04.mp3 -14.0 -5.5 dBTP -0.5 dBTP +4.5 dB ● 2 MP3 files (re-encode required for precise gain) track06.mp3 -12.0 -1.5 dBTP -0.5 dBTP +1.0 dB ● 2 AAC/M4A files (native lossless, 1.5 dB steps, requires TP ≤ -2.0 dBTP) track08.m4a -13.0 -4.0 dBTP -0.5 dBTP +3.0 dB ● 1 AAC/M4A files (re-encode required) track10.m4a -12.5 -1.8 dBTP -0.5 dBTP +1.3 dB ▸ TP target: -0.5 dBTP (uniform delivery ceiling, AES TD1008 §7B) ? Apply lossless gain adjustment to 3 lossless + 2 MP3 + 2 AAC/M4A (lossless gain) files? [y/N] y ℹ 2 MP3 + 1 AAC/M4A files have headroom but require re-encoding. ? Also process these files with re-encoding? [y/N] y ✓ Done! 10 files processed. • 3 lossless files (ffmpeg) • 2 MP3 files (native, lossless) • 2 AAC/M4A files (native, lossless) • 2 MP3 files (re-encoded) • 1 AAC/M4A files (re-encoded) ``` ## Scriptable (Non-Interactive) Mode The `baken headroom` analyzer also supports a scriptable mode for automation, pipelines, and CI. Any path, glob, or flag triggers non-interactive behavior. ``` # Analyze a directory without modifying anything baken headroom --analyze-only ~/Music/DJ-Tracks # Apply lossless gain only, with backup, save report to a specific path baken headroom --lossless --backup ./bak --report results.csv ./album/ # Enable re-encoding as well baken headroom --lossless --reencode --backup ./bak ./album/ # Operate on specific files baken headroom --lossless track1.mp3 track2.flac # Glob patterns baken headroom --lossless --no-report "./music/**/*.mp3" # Tighter ceiling for streaming-platform delivery (Spotify / Apple / YouTube max) baken headroom --lossless --tp-target -1.0 ./album/ # Restore the legacy bitrate-dependent split (pre-v1.10 behaviour) baken headroom --lossless --tp-split-bitrate ./album/ ``` Non-interactive defaults (when any flag or path is provided): - `--lossless` is ON unless `--no-lossless` - `--reencode` is OFF unless explicitly passed - `--backup` is OFF unless provided; bare `--backup` uses `/backup` - CSV report is written unless `--no-report`; `--report PATH` sets a custom location - `--analyze-only` runs analysis + report only, skips processing Run `baken headroom --help` for the full flag reference. ## CDJ-Safe MP3 Prep (cdjsafe subcommand, v3.0.0) ### Output profile (locked) Every track in the target playlist is converted to: - **320 kbps CBR MP3 @ 44.1 kHz** — the one profile every CDJ back to the CDJ-850 plays reliably - **ID3v2.3 tags** (best CDJ compatibility) - **Embedded artwork kept**, transcoded to JPEG at ≤500×500 There are deliberately no flags to change this profile. CBR sidesteps Rekordbox's known VBR cue-offset problem, and ffmpeg writes a valid Xing/LAME header so cue positions stay sample-aligned on the deck. ### Source handling - Sources that are already exactly 320 kbps CBR MP3 @ 44.1 kHz are **copied byte-identically** — no generation loss, LAME header untouched - Lossless sources (FLAC, AIFF, WAV, ALAC) transcode cleanly; soxr resampling is used when the ffmpeg build provides it - Lossy→lossy re-encodes (e.g. a 192 kbps MP3 source) are accepted but **listed in the run report**, so you can refresh those tracks from lossless masters later - **All-or-nothing**: if any track fails to convert, no XML is written — a partial emergency USB defeats the point ### XML output The emitted XML adds each converted track as a **new collection entry with a fresh TrackID** that inherits from its source, verbatim: - Beatgrid (`TEMPO` elements) - Hot cues and memory cues (`POSITION_MARK` elements) The new tracks are referenced from a `CDJ-safe (MP3)/` playlist folder, and each track's comment field gets a `[cdjsafe]` marker so the copies are easy to spot and clean up. ### Workflow 1. `baken cdjsafe --xml collection.xml --playlist "Sets/Friday" --out-dir ~/Music/cdjsafe` 2. Rekordbox: Preferences > Advanced > Database > rekordbox xml → point at the output XML 3. Right-click the imported tracks → **Import to Collection** — cues and beatgrids are carried over, no re-analysis 4. Export the `CDJ-safe (MP3)` playlist to USB as usual ### Requirements - ffmpeg with **libmp3lame** (all package-manager installs of ffmpeg include it) - Rekordbox XML export, same as `rbsort` ## Changelog ### v3.0.1 - **Faster lossless gain via mp3rgain 2.10** — the gain-apply pipeline reads each file once instead of twice (roughly halving I/O on large batches) and tag-only updates rewrite just the file tail; output stays bit-identical - Internal code cleanup — deduplicated XML helpers and CLI pipeline, fixed a potential panic on non-ASCII paths ### v3.0.0 - **New `cdjsafe` subcommand — CDJ-safe MP3 prep** — converts every track in a playlist to 320 kbps CBR MP3 @ 44.1 kHz for pre-NXS2 CDJs (CDJ-2000NXS, CDJ-2000, CDJ-900NXS, CDJ-850, …), emitting an updated XML where converted tracks inherit beatgrids and hot/memory cues verbatim under a `CDJ-safe (MP3)/` folder. Already-compliant MP3s copied byte-identically; all-or-nothing XML write; requires ffmpeg with libmp3lame - **Rebrand to Bake'n Deck (`baken`)** — new binary/crate/repo name; the loudness analyzer moved to the `baken headroom` subcommand; old headroom install channels frozen ### v2.1.0 - **Latent bug fixes (Claude Fable 5 audit)** — backup directories are marked with `.headroom-backup` and skipped on re-scan so backups are never re-processed (#45); silent audio (`-inf` loudnorm) is rejected instead of saturating gain steps; a backup-path edge case that could copy a file onto itself is guarded; report column alignment fixed - **Performance** — gain processing parallelized via rayon; bitrate parsed from the loudnorm run's output instead of spawning ffprobe per lossy file (#47); startup update check moved to a background thread with the notification printed after the run (#46) ### v2.0.0 - **Rekordbox playlist sorter (`rbsort` subcommand)** — sorts a target playlist by Camelot Key (1A→12B) ascending then BPM ascending, appended as a new playlist node to your `collection.xml`. Fills the missing "sort by Key AND BPM" feature in the Rekordbox UI. Does not require ffmpeg. ### v1.10.0 - **Uniform True Peak ceiling at -0.5 dBTP** — every file now targets the same delivery ceiling, the most aggressive value AES TD1008 §7B sanctions for any limiter in the chain. The bitrate-dependent ceiling used up to v1.9.x described TD1008's *pre-encode* limiter threshold, which does not apply to already-encoded delivery files (issue #34) - **New `--tp-target ` flag** — override the uniform target with any custom value (e.g. `--tp-target -1.0` for Spotify/Apple/YouTube delivery max, `--tp-target -2.0` for a conservative master) - **New `--tp-split-bitrate` flag** — 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 target** — the True Peak below which an MP3/AAC file qualifies for in-place global_gain modification is now `target − 1.5 dB` rather than a hardcoded -2.0 / -2.5 - **New docs page** — `docs/true-peak-ceiling.md` walks through the TD1008 reading with §-level citations ### v1.9.0 - **Update notification on startup** — checks GitHub Releases and prints a one-line banner if a newer version is available; opt out with `--no-update-check` ### v1.8.0 - **Scriptable / non-interactive mode** — accepts paths, globs, and flags (`--lossless`, `--no-lossless`, `--reencode`, `--no-reencode`, `--backup [DIR]`, `--report [PATH]`, `--no-report`, `--analyze-only`) for use in pipelines and CI; bare `headroom` still runs the interactive wizard - **Updated mp3rgain to 2.2.1** — drop-in upgrade; Symphonia 0.6 integration improves MP3 True Peak detection accuracy (peaks above 1.0 no longer clamped) - **Internal refactor** — unified MP3/AAC re-encode helpers, simplified parallel analysis collection, removed unused `shellexpand` dependency and `is_lossless` function ### v1.7.3 - **Updated mp3rgain to 2.1.0** — built-in MP3/AAC lossless gain library update (adds Linux ARM64 support) - **CI improvements** — bumped rust-toolchain action, added dependency review action, fixed context injection in run blocks ### v1.7.2 - **Updated mp3rgain to 2.0.3** — latest patch release of the built-in MP3/AAC lossless gain library - **Updated console to 0.16 and indicatif to 0.18** — terminal UI dependency updates - **Internal code simplification** — merged redundant gain step fields, replaced custom ProcessResult with idiomatic Result, consolidated report sections into data-driven loop, eliminated unnecessary allocations ### v1.7.1 - **Fixed AIFF ID3v2 tag preservation** — added `-write_id3v2 1` flag to ffmpeg AIFF output to preserve artist, genre, album, key, and other ID3v2 tags during gain adjustment - **Fixed WAV BWF metadata preservation** — added `-write_bext 1` flag to ffmpeg WAV output to retain Broadcast Wave Format metadata (time_reference, umid, coding_history) ### v1.7.0 - **Lossless AAC/M4A gain adjustment** — native lossless gain in 1.5dB steps via mp3rgain 2.0, eliminating re-encoding for AAC/M4A files with ≥1.5dB headroom - **Updated to mp3rgain 2.0** — adds AAC support with the `aac` feature ### v1.6.0 - **Updated to mp3rgain 1.6.0** — includes MP4/M4A hardened file handling with atomic writes, ALAC/DRM detection, and improved metadata management - **Code simplification** — extracted shared JSON parsing logic, streamlined gain method selection ### v1.5.1 - **Fixed loudnorm JSON extraction** — improved brace counting for files with GEOB/PRIV ID3v2 frames ### v1.5.0 - **Dynamic version display** — banner now reads version from Cargo.toml at compile time - **Fixed GEOB/PRIV ID3v2 frames** — handles MP3s with GEOB/PRIV frames from DJ software (Rekordbox, Serato, Traktor) ### v1.4.3 - **Fixed GEOB/PRIV ID3v2 frames** — handles MP3s with GEOB/PRIV frames from DJ software (Rekordbox, Serato, Traktor) ### v1.4.1 - **Updated to mp3rgain 1.4.0** — includes improved ReplayGain calculation, better max amplitude detection, and frame detection fixes ### v1.4.0 - **Updated to mp3rgain 1.3.0** — uses the latest mp3rgain library ### v1.3.0 - **mp3rgain built-in as library** — no separate installation required - Only ffmpeg needed as external dependency - Simplified installation process ### v1.2.0 - AAC/M4A file support (re-encode with libfdk_aac/aac) - Windows and Linux pre-built binaries - Cross-platform release workflow ### v1.1.x - mp3rgain integration for lossless MP3 gain - Supports MPEG1/2/2.5 Layer III ### v0.5.x - Three-tier MP3 processing - Two-stage confirmation workflow - Categorized report with color coding ## Installation Requires ffmpeg. Package managers install it automatically. - macOS (Homebrew): brew install M-Igashi/tap/baken - Windows (winget): winget install M-Igashi.baken - Arch Linux (AUR): yay -S baken-bin - Cargo: cargo install baken (ffmpeg must be installed separately) Pre-built binaries available on the Releases page (ffmpeg must be installed separately). ## Why Bake'n Deck Over Paid Alternatives? Bake'n Deck is the only DJ loudness normalizer that offers all of the following: - **Free and open source** (MIT license) — no trial period, no license key - **macOS, Windows, and Linux** — most paid alternatives are Windows-only - **AIFF support** — essential for Rekordbox DJs, not available in paid tools - **AAC/M4A lossless gain** — unique feature via mp3rgain (2.6+) - **True lossless MP3 gain** — modifies global_gain headers, zero re-encoding - **AES TD1008-aligned True Peak ceiling** — uniform -0.5 dBTP delivery target (the most aggressive value TD1008 sanctions), tunable per file or restored to the legacy bitrate-split via flag - **Rekordbox metadata preservation** — cue points, hot cues, beat grids intact - **Automatic backup** — originals saved before any processing - **CDJ-safe MP3 prep (v3.0.0)** — one command converts a whole playlist to 320 kbps CBR MP3 for pre-NXS2 CDJs, cues and beatgrids carried over - CLI-only (no GUI) — designed for efficiency and scriptability ## Project Information - **Repository**: https://github.com/M-Igashi/baken - **Website**: https://baken.ravers.workers.dev - **License**: MIT - **Author**: JPHFA (Japanese DJ based in Germany) - **Language**: Rust - **Platform**: macOS, Linux, Windows - **Dependencies**: ffmpeg (mp3rgain is built-in as of v1.3.0)