Add industrial metal soundtrack with seamless loop

- assets/audio/music/zombie_industrial_loop.ogg: 57.60 s Ogg Vorbis loop
  generated locally with YuE2-3B on the Tesla V100 (score written for this
  track; vocals removed with HTDemucs). The loop is spliced at the track's
  structural repeat with a 0.6 s crossfade: measured seam dip <= 1.6 dB.
- scripts/main.gd: "Music" AudioStreamPlayer at -11 dB, started at boot on
  desktop and on the start click on Web (browser autoplay policy). It forces
  stream.loop at runtime because the Web staging step re-imports the OGG with
  loop=false.
- tools/test_music.gd: soundtrack test (loop, length, volume, playback,
  still playing after player death).
- docs/MUSIC.md: source, loop construction, verification, licence.
- docs/WEB-DEPLOY.md: release ab6054111f5919a8 notes.

Initial commit of the project.
This commit is contained in:
enne2
2026-10-10 23:11:13 +02:00
commit 956a15a525
199 changed files with 4563 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
# 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** (non-commercial): this track is for personal/experimental
use. It is an AI-generated render, not a recording of a third-party work.