Portfolio → AI music

AI media · MusicAI music

One world, 76 tracks

An AI-generated soundtrack for the life-sim Heart Apartment — directed by ear, checked by numbers, shipped in two days.

Style anchor · home, night

夜裡的小爵士 Little Night Jazz

Finish on par with published music.

Listen to all selected tracks
Challenge

A soundtrack has to belong to one world across many scenes. Technical checks alone cannot tell whether a track fits a quiet room or an argument.

My contribution

I wrote scene briefs, listened to every render, and chose each track's place in the game. AI agents built the production scripts; the audio model generated the music.

76tracks shipped · 54 themes, 15 story cues, 7 ambience beds
244renders, each listened to, with the verdict stored next to the file
~1.5days from first planning note to game integration
0renders reached a listener without passing automatic checks
Overview

Fifty tracks that have to agree

A cozy life-sim needs hours of music that sounds like one world and stays out of the way. A model can make any single track. The hard part is fifty that agree — when the only quality test is one person saying “this feels wrong”.

  • Me: one-sentence brief per scene, every render heard, every verdict stored word for word
  • AI agents: batch runner, analysis and ranking scripts, loudness normaliser, listening page
  • Model: Stable Audio 3 Medium, local, in ComfyUI
Scene brief→Batch job→Auto-checks→Listen & comment→Ship

Rejected takes loop back as a rewritten description. Highlighted steps are human decisions.

Three calls that changed the product
  • No loops — full three-minute pieces; long sessions need variety, not seamless repeats
  • Three ambience beds cut — too noisy, and of little use in the game
  • Every use has a place — a bright Shibuya-kei take moved from title theme to “on the way out”
Highlights

Taste, numbers, and knowing which to trust

1 · “It sounds wrong” became a rule you can write down

My assessmentThe numberThe rule
Monotonous, and noisy overallHarmonic change 0.10–0.11 vs 0.21–0.56 for liked tracksSpell out the harmony: maj7 / m9 chords, slow progression
Arrangement too grand; feels oppressive50–80 % of energy below 60 Hz vs 0–12 %No drones, no sub-bass, no string pads
Too many instruments; sounds clutteredSpectral centroid 492 Hz vs 120–250 HzThree to five instruments; space between phrases
Two heatmaps of note energy over 30 seconds. The rejected take shows long flat bands on one or two notes; the style anchor shifts between notes every few seconds.
Left: rejected as monotonous on listening (0.11) — the same notes for seconds at a time. Right: the style anchor (0.22) keeps moving.
What “harmonic change” measures

The track is split into short windows; each window's spectrum is folded into the 12 musical notes; the measure is how much that note profile shifts from one window to the next. A track stuck on one chord scores low; one that moves through a progression scores high.

2 · I tested my own filter, and it failed

  • As a gate, the script was a coin toss — tracks it would cut were liked as often as tracks it passed
  • Most rejections were about mood and fit: a tone close to a phone ringing, or a mood suited to an argument scene, neither right for the setting. No spectrum threshold can see that
  • What changed: numbers diagnose a complaint; a person screens. The effort went into making listening cheap

3 · The process changed when the evidence said so

  • AI prompt expansion kept failing — it added vinyl crackle and hip-hop drums and turned “slightly uneasy” into horror. Prompts now name concrete instruments and a tempo in one sentence
  • 30-second auditions hid problems — a quiet theme passed at 30 s; all four 3-minute versions failed when a double bass entered at 1:00. Approval moved to full length
  • Percussion wouldn't behave — generate as a drumless duo, or lower the drums afterwards with source separation
Read the detail

The built-in expander added vinyl crackle, shakers and hip-hop drums, and turned “slightly uneasy” into a horror-film atmosphere that did not fit the game. From round 7, prompts named concrete instruments and a tempo in one sentence and avoided mood words like ambient or cinematic; nearly every 30-second test in that round passed.

A quiet reading theme was rated well at 30 seconds. All four three-minute versions were then rejected because a double bass came in at the one-minute mark. Quiet scenes became solo piano, and approval moved to full length.

Clap rolls and over-dense snaps could not be controlled. Two fixes: generate as a melodic duo with no drums, or remove or lower the drums afterwards with source separation, leaving the other instruments untouched.

4 · Built to ship, not to demo

  • Every render verified before anyone listens — seed, prompt, settings, real length, format; 95 jobs logged
  • One loudness standard — −18 LUFS music, −27 ambience, true peak ≤ −1 dBTP, fixed gain only
  • Provenance recorded — each shipped file maps to its render, seed and job; Stability AI Community License
  • In the game — all 76 tracks as 192 kbps MP3 with a playlist file
Read the detail

A batch runner starts one ComfyUI job per process with a 600-second limit, then decodes each file and checks seed, prompt, settings, real length and format against the job file. All 95 jobs are logged with the prompt hash and peak GPU memory.

All 76 tracks were measured to ITU-R BS.1770-4 and brought to −18 LUFS for music and −27 LUFS for ambience, true peak at or below −1 dBTP. The fix is a fixed gain only — no compression or limiting — so the sound is unchanged; six quiet tracks were left slightly under target rather than pushed through a limiter. The meter was self-tested against the standard's reference signal first.

Listen

The anchor, a favourite, and one description three ways

New batches didn't start from a blank prompt. Each job reused the full generation settings of a track I had already approved — first the night-jazz take below, later a morning piece I made myself in ComfyUI. Only the text description changed.

Style anchor · home, night

夜裡的小爵士 Little Night Jazz

Finish on par with published music.

Home, daytime

晴天的木琴 Sunny Marimba

A very high level of finish.

收拾好的午後 The Afternoon, Tidied — one description, three kept takes

Four seeds, three kept, each heard differently. This is the process itself.

Take A

Usable.

Take B

Strong sense of story.

Take C

Well-built atmosphere.

Excerpts, 60–75 s, from the loudness-matched masters.

Where the 76 tracks play

Home, dayMorning · weekend brunch on the sofa · chores · afternoon reading · cooking and dinner together
Home, nightNight rotation · livelier chat time · quiet evening · winding down after work · reading side by side
WorkTwo characters' workdays · wrapping up and overtime
Out and aboutNeighbourhood · park bench and walks · commute home at dusk · on the way out
ShopsSupermarket · plaza and department store · lifestyle store · cinema lobby
ThemeTitle · weekly recap
Story cuesBeing remembered · light teasing · waiting for the boss's reply · exhausted pause · loss and parting · apology and making up · good news · end of the week
AmbienceHome · office · park pond · supermarket · rain
Status & limits

What exists, what's proven, what isn't

Built

  • Batch runner with per-render checks
  • Ranking script, drum removal, loudness normaliser
  • Listening page with feedback capture

Verified

  • 76 tracks approved and integrated into the game (2026-09-15)
  • Loudness targets met — six quiet tracks left slightly under rather than limited
  • Ranking script tested against 241 verdicts: it doesn't work as a gate (2026-09-22)

Limits & next

  • The numbers explain complaints; they don't predict taste
  • The model can't follow bar-level structure — tracks were chosen, not composed
  • Separate music and ambience sliders: specified, not built
Opens in a new tab