71 lines
3.3 KiB
Markdown
71 lines
3.3 KiB
Markdown
# 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.
|