60 lines
3.3 KiB
Python
60 lines
3.3 KiB
Python
"""Audit the formal partner presentation bank and all nine TangoFlux sound receipts."""
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import numpy as np
|
|
from scipy.io import wavfile
|
|
|
|
ROOT=Path(__file__).resolve().parents[1]
|
|
DESIGN=ROOT/'Doc/Design/Combat/PartnerSkills'
|
|
def load(path):return json.loads(path.read_text(encoding='utf-8-sig'))
|
|
def digest(path):return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
def main():
|
|
plan=load(ROOT/'Config/Combat/partner_presentations_v1.json')
|
|
game=load(ROOT/'Config/Gameplay/greenfield.json')
|
|
assert len(plan['profiles'])==len(game['pets'])==10
|
|
assert [p['pet'] for p in plan['profiles']]==list(range(10))
|
|
assert [e['id'] for e in plan['effects']]==list(range(5,15))
|
|
assert len(set(e['path'] for e in plan['effects']))==10
|
|
for e in plan['effects']:
|
|
assert (ROOT/'AIClient'/e['path']).is_file()
|
|
assert e['poolSize']==4 and .1<=e['lifetime']<=1
|
|
assert e['loop']==(e['id'] in (5,14))
|
|
assert e['beam']==(e['id'] in (8,13))
|
|
for p in plan['profiles']:
|
|
for name,value in p.items():
|
|
if name.endswith('Effect'):assert -1<=value<15
|
|
if name.endswith('Sound'):assert -1<=value<9
|
|
assert p['abilityEffect']==p['pet']+5
|
|
manifest=load(ROOT/'Doc/Design/Sound/BattleSkills/manifest.json')
|
|
assert manifest['status']=='generated'
|
|
assert {i['id'] for i in manifest['items']}=={'Sfx_'+s for s in plan['soundIds']}
|
|
rows=[]
|
|
for item in manifest['items']:
|
|
production=item['production']
|
|
receipt=load(ROOT/production['receipt'])
|
|
record=next(r for r in receipt['items'] if r['id']==item['id'])
|
|
target=ROOT/production['output']
|
|
assert digest(target)==production['sha256']==record['outputSha256']
|
|
assert digest(ROOT/record['source'])==record['sourceSha256']
|
|
assert hashlib.sha256(json.dumps(record['request'],sort_keys=True).encode()).hexdigest()==record['requestHash']
|
|
assert record['job']['status']=='succeeded'
|
|
assert record['job']['seed']==record['request']['seed']
|
|
if item['id'] in ('Sfx_Heal','Sfx_Slow','Sfx_Lightning','Sfx_EnemyHit'):assert item['seed']==record['request']['seed']
|
|
rate,samples=wavfile.read(target);x=samples.astype(float)/32768
|
|
assert rate==44100 and samples.dtype==np.int16 and x.ndim==2 and x.shape[1]==2
|
|
assert .1<len(x)/rate<1 and np.isfinite(x).all()
|
|
peak=float(np.abs(x).max());rms=float(20*np.log10(np.sqrt(np.mean(x*x))))
|
|
assert peak<.95 and np.abs(x[:4410]).max()>.05 and np.abs(x[-10:]).max()<.003 and rms>-36
|
|
rows.append(dict(id=item['id'],seconds=len(x)/rate,peakDb=20*np.log10(peak),rmsDb=rms,
|
|
clippedSamples=int(np.sum(np.abs(x)>=.999)),sha256=digest(target),actualSeed=record['request']['seed']))
|
|
assert len(rows)==9
|
|
result=dict(status='pass',profiles=10,signaturePrefabs=10,poolRoots=76,voices=8,audio=rows,
|
|
subjectiveListening='not_asserted',releaseLicenseReview=manifest['releaseLicenseReview'])
|
|
DESIGN.mkdir(parents=True,exist_ok=True)
|
|
(DESIGN/'audio_config_validation.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
|
|
print('PASS ten partner profiles and prefabs; nine PCM sounds, source/request/output hashes, onset, fades, level, zero clipping')
|
|
|
|
if __name__=='__main__':main()
|