"""Five TangoFlux one-shots for the FireCat/RockBall skill slice; retain original jobs.""" import json from concurrent.futures import ThreadPoolExecutor from pathlib import Path import numpy as np import requests from scipy.io import wavfile import generate_enemy_sfx as audio ROOT = Path(__file__).resolve().parents[1] DESIGN = ROOT / 'Doc/Design/Sound/BattleSkills/Slice' audio.OUT = ROOT / 'Tools/output/skill_slice_sfx' audio.BUNDLE = ROOT / 'AIClient/Assets/Bundles/Sound/SFX/BattleSkills' manifest = json.loads((ROOT/'Doc/Design/Sound/BattleSkills/manifest.json').read_text(encoding='utf-8')) lengths = {'Sfx_FireCharge': .48, 'Sfx_FireLaunch': .28, 'Sfx_FireHit': .4, 'Sfx_RockHit': .32, 'Sfx_Shield': .65} if __name__ == '__main__': status = requests.get(audio.BASE+'/api/status', timeout=15).json() if not status.get('ready') or status.get('error'): raise RuntimeError('TangoFlux not ready: '+str(status)) for folder in (DESIGN, audio.OUT, audio.BUNDLE): folder.mkdir(parents=True, exist_ok=True) # The shared generator records its actual seed and request hash, not the planning manifest seed. rows = [(r['id'], r['prompt'], lengths[r['id']]) for r in manifest['items'] if r['id'] in lengths] with ThreadPoolExecutor(max_workers=2) as pool: items = list(pool.map(audio.generate, enumerate(rows))) (DESIGN/'generation.json').write_text(json.dumps({'status': 'generated', 'service': audio.BASE, 'guide': manifest['guide'], 'items': items}, indent=2), encoding='utf-8') preview = [] for item in items: _, samples = wavfile.read(ROOT/item['output']) preview.extend((samples, np.zeros((13230, 2), dtype=np.int16))) wavfile.write(DESIGN/'preview.wav', 44100, np.concatenate(preview))