← back to selected work resume →

It makes my own music finishable. It never makes a note.

The Lathe

lathe /leɪð/ noun 1 the cutting lathe The machine that writes sound into matter. A heated sapphire rides the master and carves it live, one pass, no undo, as a single unbroken spiral valley in lacquer. Every swell, every transient, every held breath transcribed into a groove a needle can later re-sing. The last physical act of mastering: the moment a mix stops being a file and becomes a thing you can hold to the light. 2 the workshop root The oldest machine on the bench. It spins a rough piece against one fixed edge and turns it down to a true, symmetrical form. Chaos in, shape out. Middle English, of Scandinavian root: a frame that holds the work, and turns it true.

Eight years of scattered sound. One place that knows what it has, and hands it back to you, smarter.

Two machines, built end to end. One reads twenty thousand files and knows what each one is. One masters a whole track by ear, blind and loudness matched, and proves what it changed.

Role
Designer, builder, sole engineer
Timeline
May 2026 to present
Stack
Astro · FastAPI · Python · Pedalboard · Whisper · Claude

Sit down to make something

The blank session waits. You half-remember a vocal you sang into your phone last Tuesday. You open Finder. iCloud hasn't downloaded the file yet. By the time it shows up, the idea is gone.

That moment, repeated a thousand times across eight years of writing music, is the gap this whole thing closes. Twenty thousand audio files: every voice memo, every jam, every bounce, every sample I've ever touched, scattered across four drives and iCloud and my desktop and friends' DMs. None of it findable. Most of it never heard again.

So I built a machine to sweep it all into one place. Scroll.

the problem Twenty thousand files. Four drives, iCloud, the Voice Memos vault, friends' DMs. No master list, no way to even ask what's in here.

the sweep Every file read by sound, fingerprinted, and flown into the bin it actually belongs in. Watch the pile become a shape.

deduped Same take, three names. The catalog hears that they are identical and folds the copies away. Twenty groups, gone.

a catalog Twenty thousand two hundred seventy nine files, read and filed. Now you can browse any category, or ask it anything. Audio 14.m4a is in Tracks, waiting. Scroll on.

Movement I · the index

AudioDex

It reads, transcribes, and catalogs twenty thousand of my own scattered files, so for the first time I know what I have, and what's worth finishing.

Voice Memos
Name Date Modified
SRC-01 · how the Mac sees it

Fire the kiln on the selected voice memo to forge its catalog entry.

Catalog standby
Field Rooftop, 6am: the city before the traffic
21:38
Summary

Pure field capture. Twenty minutes of a city waking up before the cars take it over. No part to keep, but the low hum underneath would bed a pad beautifully.

0:00[wind across the mic]

4:12[a train, far off]

11:50…first cars.

18:30[one bird, three notes, close]

field recordingcity6amtextureauto-filed
Track head to toe ★ 1 keeper
3:48
Summary

A phone memo, recorded once at 2am, never re-recorded. The audio is rough and it does not matter: the take is the song. Filed, titled, and kept so it could actually get finished.

0:00…okay, just play it, don't fix it.

0:41…head to toe, that's the line.

1:12[humming the next part]

1:31…leave it. that's the one.

voice memo2amone takethe keeper
Inbox Note to self: drop the bridge out, don't build it
0:48
Summary

Not a song. Me talking through a fix for a track I'd left half-open: pull everything but the vocal for two bars before the last chorus. Filed so I'd actually find it again.

0:03okay, the bridge. the bridge is too much.

0:19drop it out. just the vocal, two bars, right before the last chorus.

0:35then slam back in. that's the move. don't forget this one.

voice memonote to selfmix ideatracks
DEX-01 · what the catalog understands

It fills in its own entries

Before AudioDex, every one of these was a dead name in a folder: a date and a number iOS picked. You just watched the kiln read one and write its own entry.

That's one entry, the hardest kind. The other twenty thousand got the same treatment, most with no help from me: an auto-classifier reads each row's content, source, and length and files it: Jams and Field sort themselves (the first run filed 1,389 field rows and 329 jams untouched), Loops and Tracks stay curator-picked, Inbox holds the residue.

Whisper hears the words, Claude titles and summarizes, librosa stamps BPM and key. A date-and-a-number becomes a title, a sentence, and a searchable transcript. The pile becomes a thing that knows what it's holding.

This is the opposite of a sample manager. Algonaut Atlas, Waves Cosmos: they organize clean one-shots you already chose to keep, by how they sound (find me a kick). AudioDex starts from the other end of the mess: twenty thousand unnamed, half-finished files, and the one question that blocks me: what do I even have, and what's worth finishing?

Movement II · the engineer

Richard

I stopped trying to build an engineer that learns me. I built a test honest enough to prove me wrong.

Send it over

Zoom all the way in on one row in Tracks: a finished song, mixed rough, on headphones, at 2 a.m. The next step was always the lonely one: master it, A/B it against records you love, decide if it's done. So I built someone to do it with.

TRACK
head to toe
100 BPM · C major · 3:48
0:00
2y · the 2 a.m. take · from Audio 14.m4a

Hey, I'm Richard, your engineer. Send that track over and I'll bring back six options, mixed toward records you love, then A/B them for you blind and loudness-matched.

It's a finished track now. Mixed rough, on headphones, at 2 a.m. If only I had an engineer.

Behind the speech bubble, Richard runs a loop, not a button.

He reads the song section by section, plans a different master for each taste axis while carrying every past verdict as state, renders six variants, then writes how each will sound on a phone, in a car, in a club. The winner he never picks himself. That is the blind vote below, by design.

Richard's pipeline: source to analyzer to planner to renderer to translator
This diagram is an earlier plan. Two of its bets, stems-first and learning by taste, are the ones the rounds below go on to test, and one I tore down and rebuilt. The part that held is the loop itself.
Read one real step the engine plans.

The planner is handed the song's structure, the records it sits nearest, and every past verdict on this track, and it returns an ordered set of moves per stem and per section, each with its own reasoning. This is the step that reasons over state.

engineer/planner.py · make_plan() py
def make_plan(analysis, axis, pole, feedback_text=None, judgement_history=None):
    """Ask the model for a mastering plan, reasoning over the song and every past verdict."""
    personality   = PERSONALITY_PROMPTS[(axis, pole)]
    history_block = _format_feedback_history(judgement_history)          # past crowns, rolled in
    anchors       = format_for_prompt(closest_references(analysis, n=3)) # records this track sits near

    user_msg = (
        _SYSTEM_PROMPT
        + "\n\nReply with ONLY a JSON object matching this schema:\n" + json.dumps(_PLAN_SCHEMA)
        + f"\n\nPHILOSOPHY ({axis} = {pole}):\n{personality}"
        + history_block + anchors
        + f"\n\nMIX ANALYSIS:\n{_format_analysis_for_prompt(analysis)}\n"
    )

    proc = subprocess.run([CLAUDE_BIN, "-p", user_msg],
                          capture_output=True, text=True, timeout=CLAUDE_TIMEOUT_S)
    plan = _extract_json(proc.stdout)   # ordered moves per stem, per section, each with its reasoning
    plan.setdefault("bus", {"moves": [], "target_lufs": -14.0})
    return plan
The real planning call on the M1. Its output feeds the renderer; the winner is still chosen by the blind vote, not here.

You are the judge

Every idea I had about this engine had to survive one test: blind, loudness-matched, hold a number to crown your pick. Most of my ideas didn't survive it. Run it yourself and watch what your own ears do.

Round 01 split it into parts

the betThe first engine split every track into stems and mastered each piece on its own. More separation, more control. Below: one take it built that way, one untouched. Crown the one that sounds better.

head to toe blind

Sound on. You're the judge here. Listen blind, then crown one.

0:00 / 0:00 Take 1

12 switch · hold to ♛ crown · R reveal · space play when selected

Round 02 measure before you trust your ears

the betThe same master, twice. One is a few dB hotter. Crown the one that sounds better.

head to toe the same master, two levels

Sound on. You're the judge here. Listen blind, then crown one.

0:00 / 0:00 Take 1

12 switch · hold to ♛ crown · R reveal · space play when selected

Round 03 stop splitting; master the whole track

the betNo stems this time. Each take is the whole track mastered toward a different record I love, all matched to one loudness. Crown your pick.

head to toe blind · loudness-matched
⚖ loudness-matched

Sound on. You're the judge here. Listen blind, then crown one.

0:00 / 0:00 Take 1

13 switch · hold to ♛ crown · R reveal · space play when selected

The benches you just used are hand-built in the browser. See how the crossfade works.

Every take is decoded once and shared, so the same master a few dB louder is one file at two gains, never downloaded twice. The takes play as looping sources locked to one shared length, each summed through its own gain node. Switching ramps the gains over about forty milliseconds, so the playhead never reloads and never loses its place.

TheBench.astro · the crossfade graph ts
// decode every distinct clip once; the louder take reuses one file at two gains
const cache = {};
const decode = (file) => {
  if (!cache[file]) cache[file] = fetch(file).then(r => r.arrayBuffer()).then(ab => ctx.decodeAudioData(ab));
  return cache[file];
};
buffers = await Promise.all(TAKES.map(t => decode(t.file)));
loopDur = Math.min(...buffers.map(b => b.duration));   // lock every take to the shortest loop

// one persistent gain node per take, all summed into the master
chainGains = buffers.map((_, i) => {
  const g = ctx.createGain();
  g.gain.value = i === active ? TAKES[i].gain : 0;
  g.connect(master);
  return g;
});

// switch takes: ramp the chosen take up, the rest down, on the same running sources
chainGains.forEach((g, idx) =>
  g.gain.setTargetAtTime(idx === i ? TAKES[idx].gain : 0, now, 0.04));
Web Audio, no library. The A/B you just played is this graph.
The controls that make this a real listening test.
  • Blind by default. The takes are unlabeled until you crown one, so the name never votes.
  • Loudness-matched. Levels are equalized before you judge, the discipline behind ITU-R BS.1770 and the BS.1534 listening-test protocol, so the level never votes either.
  • A do-nothing baseline. Round 01 puts the untouched original in the running, so the engine has to beat doing nothing to win.
  • A planted trap. Round 02 was the same master a few dB hotter, to show how fast louder reads as better.

These are the controls a proper listening test is supposed to have. Most upload-a-file tools steer toward a sound; this one judges, blind, against a baseline.

Round 04 apprentice

the bet If which master wins depends on the track and the listener, then I should be able to learn the listener: an engine that studies every crown you give it and gets more yours each time. It even asked you questions. It was the feature I was proudest of.

It kept every pick you made above.
This failure has a name. The field found it before I did.

I hit this the hard way on an audio system, alone, and only later found the field already had a name for it. When you train a model against a judge that is itself biased, the model learns to satisfy the judge's blind spots instead of getting genuinely better. The field calls it reward-model overoptimization.

  • Gao et al., Scaling Laws for Reward Model Overoptimization. Push hard on a proxy reward and the proxy keeps climbing while the thing you actually wanted starts to fall.
  • Reward Models Are Metrics in a Trench Coat (2025). A convenient metric is not the thing you cared about. It just dresses up like it.
  • DeepMind, MusicRL. In audio, automatic scores like FAD and CLAP track human-preferred quality only weakly, and what counts as good is partly down to the listener.

The controls I reached for on my own are the standard ones: judge blind, match the loudness, keep a do-nothing baseline, never trust a single round or a single rater. I did not kill the idea of learning from votes. I killed the version that trained on a biased judge, and rebuilt it on an honest one. The lesson generalizes past audio: for anything that generates media, the evaluator is the binding constraint on quality, not the model. That is the part I find most worth building tooling around.

Round 05 the live frontier

No single master wins a whole song — so the engine never stops asking.

even within one song verse wants it processed drop wants it raw no single master fits both so it never stops asking the engine it asks the round it's least sure of you vote blind it learns from your call each round, surer what's left: real toss-ups the only calls left — blind ears decide

n=1, one builder, working in the open. −2 dBTP true-peak ceiling, a safety margin under the −1 dBTP spec, to stay clear of codec clipping.

Why this isn't just another mastering button

There's no shortage of AI that will master a track. There's nothing that masters yours inside your own library, and proves what it did, blind.

Everyone else

LANDR, Ozone, the rest are a stateless upload box: send a file, get a master, it forgets you. Some can match a reference you upload, but you are still steering toward it. None sit inside your own library and pick the winner for you, blind, then prove what they did.

The Lathe

Like the good tools, it can reference the records I love. Then it judges the result blind and loudness-matched, against doing nothing, inside my own library, where every comparison is measured, not guessed.

Blind and loudness-matched is not a feature, it is just the honest way to run the test, and the upload-a-file-get-a-master tools do not bother. The point was never to beat a label release. It was to make eight years of my own work finishable, in my own ear.

A date and a number becomes a favorite

Audio 14.m4a came in a nameless 2 a.m. phone memo with terrible audio. It went out a finished song I keep coming back to.

AudioDex found it in the pile and gave it a title: head to toe. Richard handed it back, measured blind against the records I love, and I could finally hear what it already had. I finished it. It is one of my favorite songs I have made, and the system never touched a note. It is not about fidelity. This recording is proof of that. It is about never losing the one that mattered.

It is not a demo. It runs every day against twenty thousand of my own files, and the engineer ships a master only when it beats doing nothing, blind. One person holds the whole loop, from the file on the drive to the test that proves the master. That is the point, not a limit.

The calls I'm proudest of are the ones I refused to build:

  • It won't write my posts or pitch me song ideas.
  • It won't push prompts or listen in on a session.
  • It won't finish a track, or touch a single note.
  • It won't make one creative decision for me.

This is the part that outlives my own library. Anything that learns from human taste, including the models now generating music, inherits the judge you train it against. Sharpen a biased one and it does not learn taste, it learns your blind spots, louder. So the work that mattered was never the processing. It was making a test honest enough to trust: blind, loudness matched, more than one listener, and it ships only when it beats doing nothing. Fix the evaluator before the engine. That is the instinct I would bring into a room building audio with human feedback.

Utility, not synthesis. The machine sorts, fingerprints, surfaces, and clears the friction. The artist still chooses, still drags, still arranges. The Lathe
Before you hear it, the back of the machine.

One person designed and built every layer of this: the catalog and its API, the verb contract the surfaces are built on, the front end you are reading, and the classifier that filled it.

The Console architecture: capture sources, the catalog and engine, the inboxes, and the surfaces
Twenty thousand of my own files, read by sound and filed without me. Whisper hears the words, Claude titles each one, librosa stamps key and tempo, all held in one SQLite catalog and served over a small FastAPI on the M1. The diagram is the rest of the wiring.
The verb contract: the read and write endpoints every surface runs on
Every surface talks to the same small set of verbs over that one API. The interfaces are disposable; the catalog and the verbs are not. When two surfaces got deleted in May, the catalog did not move.
The Build 3 Max device killed by two architectural walls, reframed into Build 4
Not everything I built survived. An earlier version lived inside the DAW as a Max device and hit two walls I could not engineer around, so I stopped pushing on a dead approach and wrote into the DAW's own browser instead. The judgment was knowing which wall was load-bearing and which was a detour.

The surfaces are disposable. The catalog, the verbs, and the calls about what not to build are not.

Tolo.Cloud
press power to wake
← back to selected work