CoProducer Measure a mix
Two lacquered master reels on black marble, one rimmed in cyan and one in magenta, with a closed vault drawer between them

Workflow · 8 October 2026 · 10 min

A 432 alternate master should never cost you the original

NoDAW Labs · Lacquer Vol. 05

Treat a 432 Hz alternate as a second deliverable, not an edit of the first. Lock the approved 440 master read-only, render the alternate once at the exact 432/440 ratio into its own folder, name it so nobody can confuse the two, write down what you did, and re-check runtime, tempo, loudness, and identifiers before it leaves the room.

The way it usually goes: the record is mastered, approved, and sitting in the client folder. Then somebody plays the artist a 432 version on a phone in the car. They light up. Now they want it on the deluxe, or on a separate listening edition, or just "both, please." That's a reasonable creative request. What goes wrong usually isn't the conversion. It's what happens three weeks later, when nobody can say which WAV is the master, the distributor has a file called final_432_NEW.wav, and the lyric video is drifting off the vocal by the second chorus.

So this one isn't about whether 432 sounds better. That's taste, and the artist gets to decide it. It's about building the alternate as a real deliverable: its own folder, its own name, its own notes, its own QC pass, with the approved original sitting untouched the whole time. If you want the math first, What 432 Hz actually changes in a finished master walks through it. Here we're building the thing.

Two masters, one source of truth

A classic 432 retune of a 440 record is a different file in every way that matters downstream. The pitch center sits about 31.77 cents lower. The runtime is about 1.85% longer. The tempo drops by the same ratio, so 120 BPM becomes roughly 117.82. Any timecode built on the original (cue sheets, video edits, CD indexes, DJ grids, sync points) is now wrong for the new file. It's a sibling, not a replacement.

The simplest way to keep that straight is physical separation. One folder per release with four rooms in it:

The read-only flag sounds fussy until the day a batch tool or a tired assistant writes over the approved file. Your operating system will say no before anyone else gets the chance to.

Names that survive a handoff

File names are the only metadata guaranteed to travel. Tags get stripped by upload forms, chat apps rename things, and folders get flattened in zips. So put the facts in the name: Artist_Title_Version_Pitch_Rate_Depth. The approved file becomes Artist_Title_Master_440_48k_24b.wav. The alternate becomes Artist_Title_432Master_48k_24b.wav. Add a loudness suffix like _-14LUFS only when you deliberately normalized it, because a suffix that describes processing that never happened is worse than no suffix.

The public title deserves the same care. "Title (432 Hz Alternate Master)" tells a listener, a playlist curator, and a distributor exactly what they're getting. Don't call it a remaster if no remastering happened. Don't dress the artwork in lab seals or certification badges that imply something was clinically measured. A consistent mark or color shift is enough to tell the two versions apart.

Render it once and write down what you did

Here's the whole workflow as one script you can run. It builds a synthetic "approved master" (an A major pad with a held A4 and a 120 BPM click-kick, generated in code so nobody mistakes it for a real record), locks it read-only in SOURCE, renders the alternate with an exact-ratio resample, makes a labeled MP3 from the 24-bit alternate, measures both versions, and writes the notes file.

One detail in the filter chain is worth slowing down for. FFmpeg's asetrate only takes whole numbers, and 48000 × 432/440 is 47127.27, so the obvious one-liner lands a hair off the target. Resampling to 88000 first means the relabel is 88000 to 86400, which is exactly 432/440. Then it comes back down to 48 kHz with the SoX resampler at high precision. It's a small thing, but it's the difference between documenting the ratio and approximating it.

#!/usr/bin/env python3
"""08_alternate_master.py: build a 432 alternate master next to an approved 440 master,
without ever touching the original. SYNTHETIC AUDIO ONLY (generated below).
Needs: python3 + numpy, ffmpeg/ffprobe on PATH.
Usage: python3 08_alternate_master.py [workdir]"""
import hashlib, json, os, re, stat, subprocess, sys
import numpy as np

SR, SRC_REF, TARGET = 48000, 440.0, 432.0
RATIO = TARGET / SRC_REF
root = os.path.abspath(sys.argv[1] if len(sys.argv) > 1 else "Artist_Title_release")
dirs = {k: os.path.join(root, k) for k in ("SOURCE", "RETUNED_MASTER", "DELIVERY", "NOTES")}
for d in dirs.values():
    os.makedirs(d, exist_ok=True)

def run(cmd):
    return subprocess.run(cmd, capture_output=True, text=True, check=True)

def sha(p):
    return hashlib.sha256(open(p, "rb").read()).hexdigest()

def decode(p):
    raw = subprocess.run(["ffmpeg", "-v", "error", "-i", p, "-f", "f32le", "-ac", "2", "-"],
                         capture_output=True, check=True).stdout
    return np.frombuffer(raw, np.float32).reshape(-1, 2)

def probe(p):
    j = json.loads(run(["ffprobe", "-v", "error", "-show_streams", "-show_format", "-of", "json", p]).stdout)
    s = j["streams"][0]
    return dict(duration=float(j["format"]["duration"]), rate=int(s["sample_rate"]),
                channels=s["channels"], bits=s.get("bits_per_raw_sample") or s.get("bits_per_sample"))

def loudness(p):
    err = run(["ffmpeg", "-nostats", "-hide_banner", "-i", p, "-af", "ebur128=peak=true:framelog=quiet",
               "-f", "null", "-"]).stderr
    s = err[err.rfind("Summary:"):]
    return (float(re.search(r"I:\s+(-?[\d.]+) LUFS", s).group(1)),
            float(re.search(r"Peak:\s+(-?[\d.]+) dBFS", s).group(1)))

def peak_hz(x, lo, hi):
    m = x.mean(axis=1)[: SR * 8] * np.hanning(SR * 8)
    sp = np.abs(np.fft.rfft(m, 16 * len(m)))
    f = np.fft.rfftfreq(16 * len(m), 1 / SR)
    band = (f > lo) & (f < hi)
    return f[band][np.argmax(sp[band])]

def bpm(x):
    env = np.abs(x.mean(axis=1))
    hop = SR // 1000                       # 1 ms frames
    e = env[: len(env) // hop * hop].reshape(-1, hop).max(axis=1)
    hits = np.flatnonzero((e[1:] > 0.5) & (e[:-1] <= 0.5)) + 1
    hits = hits[np.insert(np.diff(hits) > 200, 0, True)]
    return 60000.0 * (len(hits) - 1) / (hits[-1] - hits[0])   # average over every beat

# 1) synthetic "approved" 440 master: A major pad + held A4 + a 120 BPM click-kick, 24 s
t = np.arange(SR * 24) / SR
pad = sum(a * np.sin(2 * np.pi * f * t) for f, a in ((220, .18), (277.18, .12), (329.63, .12), (440, .20)))
kick = np.zeros_like(t)
for n in range(48):                         # one hit every 0.5 s = 120 BPM
    i = int(n * 0.5 * SR); seg = np.arange(min(4800, len(t) - i)) / SR
    kick[i:i + len(seg)] += 0.9 * np.sin(2 * np.pi * 55 * seg) * np.exp(-seg * 30)
mix = np.stack([pad * 0.9 + kick, pad * 0.8 + kick], 1) * 0.6
src = os.path.join(dirs["SOURCE"], "Artist_Title_Master_440_48k_24b.wav")
if os.path.exists(src):
    os.chmod(src, stat.S_IWUSR | stat.S_IRUSR)
subprocess.run(["ffmpeg", "-y", "-v", "error", "-f", "f32le", "-ar", str(SR), "-ac", "2", "-i", "-",
                "-c:a", "pcm_s24le", src], input=mix.astype(np.float32).tobytes(), check=True)
os.chmod(src, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)   # approved master is read-only
src_hash = sha(src)

# 2) classic exact-ratio retune: 88000 -> relabel as 86400 -> back to 48000 (432/440 exactly)
out = os.path.join(dirs["RETUNED_MASTER"], "Artist_Title_432Master_48k_24b.wav")
chain = "aresample=88000:resampler=soxr:precision=28,asetrate=86400,aresample=48000:resampler=soxr:precision=28"
run(["ffmpeg", "-y", "-v", "error", "-i", src, "-af", chain, "-c:a", "pcm_s24le", out])

# 3) a labeled delivery encode made from the 24-bit alternate, never from another encode
mp3 = os.path.join(dirs["DELIVERY"], "Artist_Title_432Master_320k.mp3")
run(["ffmpeg", "-y", "-v", "error", "-i", out, "-c:a", "libmp3lame", "-b:a", "320k",
     "-metadata", "title=Title (432 Hz Alternate Master)", "-metadata", "artist=Artist", mp3])

# 4) measure both and write the notes file
a, b = decode(src), decode(out)
pa, pb, ma = probe(src), probe(out), probe(mp3)
la, lb = loudness(src), loudness(out)
corr = float(np.corrcoef(b[:, 0], b[:, 1])[0, 1])
notes = {
    "source_file": os.path.basename(src), "source_sha256": src_hash[:16] + "...",
    "source_reference_hz": SRC_REF, "target_hz": TARGET, "ratio": round(RATIO, 6),
    "cents": round(1200 * np.log2(RATIO), 2), "mode": "classic resample (pitch and time move together)",
    "filter_chain": chain, "loudness_processing": "none",
    "duration_s": [round(pa["duration"], 3), round(pb["duration"], 3)],
    "expected_duration_s": round(pa["duration"] / RATIO, 3),
    "measured_A4_hz": [round(peak_hz(a, 420, 460), 2), round(peak_hz(b, 420, 460), 2)],
    "measured_bpm": [round(bpm(a), 2), round(bpm(b), 2)],
    "integrated_lufs": [la[0], lb[0]], "true_peak_dbtp": [la[1], lb[1]],
    "format_out": f'{pb["rate"]} Hz / {pb["bits"]}-bit / {pb["channels"]} ch',
    "lr_correlation_out": round(corr, 3),
}
json.dump(notes, open(os.path.join(dirs["NOTES"], "render-notes.json"), "w"), indent=2)

tags = run(["ffprobe", "-v", "error", "-show_entries", "format_tags=title", "-of", "default=nw=1:nk=1", mp3]).stdout.strip()
print("tree:")
for d in sorted(dirs):
    for f in sorted(os.listdir(dirs[d])):
        print(f"  {d}/{f}")
print("notes:", json.dumps(notes, indent=2))
print("delivery title tag :", tags, f'({ma["duration"]:.3f} s mp3)')
print("source untouched   :", sha(src) == src_hash)
try:
    open(src, "ab").close(); print("source writable    : yes (fix permissions!)")
except PermissionError:
    print("source writable    : no (read-only, as it should be)")

And this is what it printed on the box, unedited:

tree:
  DELIVERY/Artist_Title_432Master_320k.mp3
  NOTES/render-notes.json
  RETUNED_MASTER/Artist_Title_432Master_48k_24b.wav
  SOURCE/Artist_Title_Master_440_48k_24b.wav
notes: {
  "source_file": "Artist_Title_Master_440_48k_24b.wav",
  "source_sha256": "49eeb5eacb852f64...",
  "source_reference_hz": 440.0,
  "target_hz": 432.0,
  "ratio": 0.981818,
  "cents": -31.77,
  "mode": "classic resample (pitch and time move together)",
  "filter_chain": "aresample=88000:resampler=soxr:precision=28,asetrate=86400,aresample=48000:resampler=soxr:precision=28",
  "loudness_processing": "none",
  "duration_s": [
    24.0,
    24.444
  ],
  "expected_duration_s": 24.444,
  "measured_A4_hz": [
    440.0,
    432.0
  ],
  "measured_bpm": [
    120.01,
    117.83
  ],
  "integrated_lufs": [
    -15.9,
    -16.0
  ],
  "true_peak_dbtp": [
    -2.5,
    -2.5
  ],
  "format_out": "48000 Hz / 24-bit / 2 ch",
  "lr_correlation_out": 0.999
}
delivery title tag : Title (432 Hz Alternate Master) (24.480 s mp3)
source untouched   : True
source writable    : no (read-only, as it should be)

Reading the printout like a mastering engineer

Every number in that notes file is there to answer a question somebody will ask you later.

Measured A4 went from 440.00 to 432.00 Hz. That's the proof the ratio is real and not a guessed pitch knob. If you ever see 431.8 or 432.3 here, something in the chain is rounding.

Duration went from 24.000 to 24.444 seconds, matching the expected value to the millisecond. On a real four-minute song that's about 4.4 extra seconds. On a ten-minute ambient piece it's over 11. That matters more than it looks, and we'll get to why.

Tempo measured 120.01 and 117.83 BPM. The script times every kick on a 1 ms grid, so the last decimal wobbles a little. The theory says 117.82. Close enough to confirm the speed moved with the pitch, which is what classic resampling should do.

Loudness moved by a tenth of a LU and true peak didn't move at all. That's the result you want. A resample isn't a loudness process, and it shouldn't act like one. If your alternate comes out a dB hotter, something else got added to the chain, and that's a second variable riding along with the tuning.

The MP3 reports 24.480 seconds. That's 36 ms longer than the WAV it came from, because encoders add padding at the start and end. It's a small, real reason to pull runtimes for cue sheets and video from the lossless file, not the encode. And because the encode reuses the 24-bit alternate, you're never stacking one lossy pass on another, which is exactly how re-encoding eats true-peak headroom.

Source untouched: True, and not writable. That's the line that lets you sleep.

What changes between the two deliverables

PropertyApproved 440 masterClassic 432 alternateWhat to do about it
A4 reference440 Hz432 Hz (ratio 0.981818, about −31.77 cents)State it in notes and in the version title
RuntimeOriginalAbout 1.85% longerRebuild cue sheets, video, CD indexes from the WAV
TempoOriginal BPMBPM × 0.981818Update DJ grids, stems, and any tempo metadata
Loudness and true peakAs masteredShould land within a few tenthsMeasure; don't add a loudness advantage by accident
File name..._Master_440_48k_24b..._432Master_48k_24bNever reuse or overwrite the original name
Public titleTitleTitle (432 Hz Alternate Master)No "remaster" unless it was remastered
Lyric and visual syncLockedDrifts unless rebuiltRe-time it, or use a time-preserving shift and audition hard

The runtime ripple most people miss

A longer file breaks anything that was timed against the shorter one. Lyric videos and visualizers drift a little more every bar. Continuous mixes and gapless album transitions land late. Live playback cues fire early. If the alternate needs to sit under unchanged picture, you have two honest choices: re-time the visuals to the new audio, or render with a time-preserving pitch shift instead and listen carefully for smeared transients and swirly reverb tails. Neither is automatically better. The trade-offs are laid out in Resampling, pitch shifting, and tempo change are three different jobs.

Then there's the identifier question, and this one surprises people. Your distributor will want to know if the alternate gets its own ISRC. The IFPI ISRC Handbook (4th edition, Annex A.10.2) says that when a recording's length changes through something like a speed change, without new creative input, a new code is not assigned if the length difference is under 10 seconds, and is assigned if it's 10 seconds or more. At 1.85%, a track has to run about nine minutes before a classic 432 retune adds 10 seconds. So for most songs, the handbook's length rule alone doesn't call for a new code. Distributors have their own systems, though, and some won't accept two different audio files on one code. Ask your distributor or your national ISRC agency before upload, not after. Write their answer in NOTES.

QC the whole file, not the chorus

The script measures. You still have to listen. Play the alternate from the first transient to the last tail. You're listening for a clipped start, a truncated reverb, a channel swap, or a click at the edit. Confirm the format line reads what you expect: 48 kHz, 24-bit, two channels. If the mix leans on wide stereo processing, sum to mono once and make sure nothing vanishes. The script's L/R correlation of 0.999 is about as safe as it gets, but a real record won't be that tidy.

Then do a short synchronized A/B on a passage the artist knows by heart, at matched level. The point isn't to prove anything. It's to make sure the version you're about to deliver is the version that won in the car. If the intro gets better and the chorus loses its push, that's useful information. Some records want the alternate as an intro-to-outro listening edition. Some want it as one track on a deluxe, and some don't want it at all.

Talking to the client like a grown-up

Your delivery note can be short and still say everything: "432 Hz alternate master, rendered from the approved 440 master. Ratio 432/440, about 31.77 cents lower. Classic resample, so it runs about 1.85% longer and the tempo drops by the same ratio. No additional mastering or loudness processing." That's it. You can describe the character the artist hears. Lower, heavier, a little more suspended, a touch slower are all fair words for creative intent.

Stay away from anything that sounds like a medical or cosmic claim. You don't need it, it isn't supported, and it makes the whole release look less serious. The alternate is a creative version, and creative is enough.

Approve one, then repeat it

If this is an album, don't convert twelve songs because the first one sounded good. Approve the naming pattern, the render mode, and the loudness rule on one representative track. Then run the rest against a read-only copy of the source folder, and spot-check the shortest, longest, loudest, and most dynamic files. Album work is a batch problem, the same way album consistency is a batch problem, and the next essay in this series, Batch retune a folder to 432 Hz without damaging a master, is about doing that part safely.

Should I overwrite the 440 master with the 432 version?
No. Keep the approved 440 master untouched and read-only, and render the 432 alternate into a separate folder with a different file name. The alternate has a different pitch center, runtime, and tempo, so it is a second deliverable.
How much longer is a 432 Hz version of a song?
With classic resampling, about 1.85% longer, because the playback rate drops by 432/440. A four-minute song gains about 4.4 seconds and 120 BPM becomes about 117.82 BPM. A time-preserving pitch shift keeps the runtime but can add artifacts.
Does a 432 Hz alternate need its own ISRC?
The IFPI ISRC Handbook says a speed-only length change under 10 seconds does not call for a new code, and 10 seconds or more does. A classic retune only adds 10 seconds on tracks of about nine minutes or longer. Distributors have their own rules, so confirm with yours before upload.
What should I name a 432 Hz alternate master file?
Put the facts in the name, such as Artist_Title_432Master_48k_24b.wav, and use a public title like Title (432 Hz Alternate Master). Add a LUFS suffix only if you actually normalized the file.
Will the 432 version be louder or quieter?
A clean resample should land within a few tenths of a LU and a similar true peak. In our synthetic test it moved 0.1 LU with no true-peak change. A bigger difference means something else was added to the chain.

A free one-pager

The checklist we run before every release.

Loudness, true peak, mono, tails, export settings and the metadata basics, on one page. Leave your email and it opens straight away, or read it here first. No email needed for that.