Files
zombie-fps/docs/MUSIC.md
T

3.3 KiB

Soundtrack — industrial metal loop

Endless survival loop played from the first frame, at -11 dB, independent of gameplay state.

Source

Generated locally (2026-10-10) with YuE2-3B Q8_0 through the audio.cpp CUDA build for the Tesla V100 (~/dev/audio.cpp, cmake -DCMAKE_CUDA_ARCHITECTURES=70), seed 31337, 16 steps, cot=melody + an external ABC score written for this track (K:Em Phrygian, Q:1/4=168, 96 bars; the model rendered it at a perceived 112.5 BPM). Style prompt: instrumental industrial metal, Nine Inch Nails meets the Quake 2 soundtrack, machine drums, palm-muted downtuned guitars, atonal synth stabs, no vocals.

--lyrics "[instrumental]" does not suppress singing (verified: male shouts 0:52-1:17 and 1:37-2:35). The instrumental was therefore obtained by HTDemucs vocal removal (--task sep --family htdemucs, input resampled to 44.1 kHz, RTF 0.049) and remixed as drums + bass + other.

Working files: ~/yue2-out/zombie-industrial/.

Loop construction

The track has a structural repeat (bars 24-30 ≈ 46-52, spectral similarity 0.95), so the loop splices at matching material instead of cutting arbitrarily:

  • region 51.37 s → 108.97 s of the instrumental master = 27 bars (bar = 2.1333 s, 112.5 BPM);
  • rotation by one tail segment plus a 0.60 s equal-power crossfade;
  • result: 57.60 s, seam dip ≤ 1.6 dB in 20 ms windows, sample step 0.04 (inaudible);
  • perceptual check on a 3 s + 3 s excerpt around the seam: no click, no level hole, natural continuation.

A longer variant (132 s) was rejected: its crossfade cancels (a -48 dB hole) because the two overlapped sections are out of phase.

Asset and import

assets/audio/music/zombie_industrial_loop.ogg — Ogg Vorbis q6, 48 kHz stereo, 1.0 MB, -14 LUFS / -1.0 dBTP. Import: loop=true, bpm=112.5, beat_count=108, bar_beats=4.

The Web staging step (tools/prepare_web.py) copies the asset but ignores *.import, and the staging import regenerates it with loop=false. main.gd therefore sets stream.loop = true at runtime: keep that line, it is what makes the browser build loop.

Runtime wiring

scripts/main.gd: _setup_music() creates the AudioStreamPlayer named Music (group music), _start_music() starts it once, _restart_music() restarts it if the loop flag is ever absent. On Web the start is deferred to the click that captures the mouse, because browsers only allow audio after a user gesture. Music keeps playing while the player is dead; R reloads the scene and the track restarts with it.

Verification

godot --headless --path . --script res://tools/test_music.gd
godot --display-driver headless --audio-driver PulseAudio --path . --script res://tools/test_music.gd
godot --headless --path . -- --smoke

Both runs PASS: node present, loop=true, length 57.60 s, volume -11 dB, playback advancing (confirmed on the real PulseAudio device, not only the Dummy driver), music still playing after player death. Grenade, wave, death and damage-feedback tests also pass unchanged.

License

YuE2-3B weights are CC BY-NC 4.0 — a fact about the model, not about this track.

The project owner states that they hold the full licence and title to the generated track and has authorised its use, including public deployment, on the same basis as the Valve assets already shipped in this repository.