Master a track

Mastering takes a finished stereo mix and prepares it for release: balanced tone, controlled dynamics, a safe stereo image, and the right loudness for where it will be played, without clipping. ferraus master does all of it in one command, and every stage is an ordinary ferraus command you can inspect, edit, and re-run. Outputs are trimmed copies of what ferraus 0.1.0 printed for a 21-second test mix.

You need: a stereo mix (mix.wav) with some headroom (peaks below about -3 dBFS, no limiter on the mix bus). No downloads are needed.

1. Measure the mix

ferraus master analyze mix.wav --json
{"ok": true, "command": "master analyze",
 "metrics": {"integrated_lufs": -19.61, "true_peak_dbtp": -4.94, "looks_mastered": false},
 "result": {"loudness": {"integrated_lufs": -19.61, "loudness_range_lu": 0.84, "true_peak_dbtp": -4.94, "crest_factor_db": 17.02, "plr_db": 14.67},
            "tonal_balance": {"against": "genre curve: acoustic", "rms_deviation_db": 3.23,
                              "largest_deviations": [{"center_hz": 10000.0, "delta_db": 8.2, "direction": "too much"},
                                                     {"center_hz": 800.0, "delta_db": -7.0, "direction": "too little"}, ...]}, ...}}

This is the report the automatic master decides from: how loud the mix is, how much peak room it has, and how its tone compares with a typical curve for the genre (guessed here as "acoustic"; set it with --genre pop|hiphop|edm|rock|acoustic|classical|jazz|podcast).

Listen for the same things before you start: harsh or dull top end, boomy or thin bass, and whether the loud parts already sound squashed.

2. Master it

ferraus master mix.wav -o master.wav --report report.json --ab --json
{"ok": true, "command": "master",
 "outputs": [{"path": "master.wav"}, {"path": "master.ab-before.wav", "role": "ab-before"},
             {"path": "master.ab-after.wav", "role": "ab-after"}, {"path": "report.json", "role": "report"}],
 "params": {"target": "streaming", "genre": "acoustic", "intensity": "medium", "warmth": "15%", "width": "100%", ...},
 "metrics": {"integrated_lufs": -14.0, "true_peak_dbtp": -1.02, "limiter_gain_reduction_db": 0.3,
             "target_reached": true, "verify_pass": true, "ab_loudness_difference_lu": 0.0}}

The default target is streaming: -14 LUFS integrated, true peak at or below -1 dBTP, which is where Spotify, YouTube, Tidal, and Amazon normalize playback. The master also trimmed the 2-second silent tail of the test mix (--trim-silence -70dB; off keeps it).

Listen to the A/B pair, not the master against the mix. master.ab-before.wav and master.ab-after.wav are matched in loudness (here within 0.0 LU), so you hear what mastering changed rather than "louder sounds better". Listen for: a clearer, more even tone; bass that is solid but not boomy; no pumping (the level dipping on every kick); no harshness on loud cymbals or vocals.

3. Check it against the delivery spec

ferraus master verify master.wav --target streaming
{"pass": true, "target": {"name": "streaming", "lufs": -14.0, "true_peak_dbtp": -1.0}, "tolerance_lu": 0.5,
 "checks": [
   {"check": "loudness", "status": "pass", "value": -14.0, "limit": "-14 LUFS ± 0.5 LU"},
   {"check": "true_peak", "status": "pass", "value": -1.02, "limit": "<= -1 dBTP (4x oversampled)"},
   {"check": "clipping", "status": "pass", "value": 0},
   {"check": "dc_offset", "status": "pass", "value": 0.00011},
   {"check": "out_of_phase_bass", "status": "pass", "value": 1.0},
   {"check": "correlation", "status": "pass", "value": 1.0}, ...]}

A failing file exits with code 9 and a runnable fix for each failed check. The unmastered mix, for example:

ferraus master verify mix.wav --target streaming --json
{"ok": false, "metrics": {"pass": false, "failed_checks": ["loudness"],
  "checks": [{"check": "loudness", "status": "fail", "value": -19.61,
              "details": "integrated loudness -19.61 LUFS is -5.61 LU from the -14 LUFS target",
              "fix": "normalize:lufs=-14LUFS"}, ...]},
 "error": {"code": "verification_failed", "exit_code": 9, ...}}

4. Change what the master does

Plan without writing audio, edit the plan, then run the edited plan:

ferraus master plan mix.wav --target apple --intensity light -o plan-apple.json
{"version": 1,
 "target": {"name": "apple", "lufs": -16.0, "true_peak_dbtp": -1.0},
 "intensity": {"name": "light", "limiter_max_gain_reduction_db": 2.0},
 "stages": [
   {"stage": "preflight", "op": "dc-remove", "args": {"freq": "5Hz"}, "why": "remove DC offset (5 Hz high-pass)"},
   {"stage": "preflight", "op": "silence trim", "args": {"threshold": "-70dB", "keep": "10ms"}, ...},
   {"stage": "corrective_eq", "op": "eq", "args": {"band": ["peak:25Hz:+3dB:q=4.32", ...], "linear_phase": "true"},
    "why": "match-eq toward the acoustic genre curve at 50% (1/3-octave bands, at most 4 dB per band; ...)"},
   {"stage": "corrective_eq", "op": "highpass", "args": {"freq": "20Hz", "order": "4"}, ...},
   {"stage": "dynamics", "op": "multiband", "args": {"crossovers": "120Hz,2kHz,10kHz", "ratio": "1.5:1", ...}, ...},
   {"stage": "dynamics", "op": "compress", "args": {"threshold": "-22dB", "ratio": "1.5:1", ...}, ...},
   ...]}

Every stage is a ferraus command with its arguments, and why explains the choice. Change a value (say, the compressor threshold), delete a stage you do not want, then:

ferraus master mix.wav --plan plan-apple.json -o master-apple.wav
ferraus master verify master-apple.wav --target apple

Common adjustments without editing a plan:

You hearTry
Too bright or too dull compared with a record you like--reference ref.wav --match-amount 75%
Squashed, lifeless--intensity light
Needs to be louder (club, DJ)--target club --intensity heavy
Too wide, weak in mono--width 90% or --no-widen
Muddy low end in stereo--bass-mono 150Hz
Added grit you do not want--warmth 0%

Targets: streaming (-14 LUFS), apple (-16), youtube (-14), club (-8, -0.3 dBTP), cd (-10, 16-bit 44.1 kHz), broadcast (-23, EBU R128; --standard atsc for -24 LKFS), podcast (-16 stereo, -19 mono), or custom with --lufs and --true-peak. See Loudness standards.

5. Write the release files

ferraus master deliver master.wav --tags title=Demo,artist=Ferraus --loudness-sheet -o release/demo.wav
release/demo.wav24.wav   release/demo.wav16.wav   release/demo.mp3
release/demo.loudness.json   release/demo.loudness.csv
format,path,sample_rate,channels,bit_depth,bitrate,duration_s,integrated_lufs,loudness_range_lu,short_term_max_lufs,true_peak_dbtp,sample_peak_dbfs,plr_db,measured
wav24,release/demo.wav24.wav,48000,2,24,,19.597,-14.0,0.25,-13.74,-1.02,-1.11,12.98,decoded deliverable
wav16,release/demo.wav16.wav,44100,2,16,,19.597,-14.02,0.26,-13.76,-1.05,-1.32,12.97,decoded deliverable
mp3,release/demo.mp3,44100,2,,320000,19.597,-14.04,0.26,-13.78,-0.85,-0.85,13.2,decoded deliverable

Every deliverable is decoded and measured again. Note the MP3's true peak (-0.85 dBTP): lossy encoding adds small overshoots, so check the sheet before you upload. Add flac and aac with --formats wav24,flac,aac (AAC needs FFmpeg), and an ISRC with --isrc.

Reference

master · master analyze · master plan · master verify · master deliver · normalize