Files
zombie-fps/tools/extract_weapon_audio.py
T
enne2 956a15a525 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.
2026-10-10 23:11:13 +02:00

29 lines
1.8 KiB
Python

"""Copy original local Valve assets, validate WAV/MDL, record SHA256 provenance."""
import pathlib, shutil, struct, wave, hashlib, json
project = pathlib.Path(__file__).resolve().parents[1]
source = pathlib.Path.home()/'.steam/steam/steamapps/common/Half-Life/valve'
files = ['models/v_9mmar.mdl','models/w_9mmar.mdl','models/p_9mmar.mdl']
files += ['sound/weapons/'+n+'.wav' for n in ['hks1','hks2','hks3','dryfire1']]
files += ['sound/items/'+n+'.wav' for n in ['clipinsert1','cliprelease1','guncock1']]
files += ['sound/zombie/'+p.name for p in sorted((source/'sound/zombie').glob('*.wav'))]
files += ['sound/player/pl_metal%d.wav'%i for i in range(1,5)]
files += ['sound/debris/bustglass%d.wav'%i for i in range(1,4)]
manifest=[]
for relative in files:
src=source/relative
dst=project/'assets'/('weapons/'+src.name if relative.startswith('models/') else 'audio/'+relative.removeprefix('sound/'))
dst.parent.mkdir(parents=True,exist_ok=True)
shutil.copyfile(src,dst)
row={'source':relative,'destination':str(dst.relative_to(project)),'sha256':hashlib.sha256(src.read_bytes()).hexdigest()}
assert src.read_bytes()==dst.read_bytes()
if src.suffix=='.wav':
with wave.open(str(dst)) as w:
assert w.getcomptype()=='NONE'
row.update(channels=w.getnchannels(),bits=w.getsampwidth()*8,rate=w.getframerate(),duration=w.getnframes()/w.getframerate())
else:
d=dst.read_bytes(); assert d[:4]==b'IDST' and struct.unpack_from('<i',d,4)[0]==10
row.update(textures=struct.unpack_from('<i',d,180)[0],sequence_groups=struct.unpack_from('<i',d,172)[0])
manifest.append(row)
(project/'assets/half_life_manifest.json').write_text(json.dumps(manifest,indent=2)+'\n')
print('Validated and copied',len(manifest),'original assets; SHA256 manifest written.')