"""L6 only: decode saved L5 audio via existing converter."""
import asyncio,array,hashlib,json,math,pathlib,subprocess,sys,time
sys.path.insert(0,str(pathlib.Path.cwd()/'server'))
from device_gateway import speech
root=pathlib.Path('.cache/speech-diagnostics')
async def main():
 rows=[]
 for lang in ['zh','en']:
  source=root/('tts-'+lang+'.source');data=source.read_bytes()
  probe=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_streams','-show_format','-of','json',str(source)]))
  processes=[];original=asyncio.create_subprocess_exec
  async def traced(*a,**k):
   p=await original(*a,**k);processes.append(p);return p
  asyncio.create_subprocess_exec=traced;t=time.perf_counter()
  try:pcm=await speech.audio_to_pcm(data)
  finally:asyncio.create_subprocess_exec=original
  latency=(time.perf_counter()-t)*1000
  assert pcm and len(pcm)%2==0 and not pcm.startswith(b'RIFF') and all(p.returncode==0 for p in processes)
  samples=array.array('h');samples.frombytes(pcm)
  if sys.byteorder!='little':samples.byteswap()
  (root/('tts-'+lang+'.pcm')).write_bytes(pcm)
  row={'language':lang,'source_bytes':len(data),'source_format':probe['format'].get('format_name'),'source_duration':probe['format'].get('duration'),'source_streams':probe['streams'],'ffmpeg_ms':latency,'ffmpeg_exit_codes':[p.returncode for p in processes],'pcm_bytes':len(pcm),'pcm_duration':len(pcm)/88200,'pcm_sha256':hashlib.sha256(pcm).hexdigest(),'chunk_count':(len(pcm)+7055)//7056,'last_chunk_bytes':len(pcm)%7056 or 7056,'output':'s16le 44100Hz mono','peak':max(abs(x) for x in samples),'rms':math.sqrt(sum(x*x for x in samples)/len(samples)),'clipping_samples':sum(abs(x)>=32767 for x in samples)}
  rows.append(row);(root/'l6-conversion.json').write_text(json.dumps(rows,indent=2));print(json.dumps(row),flush=True)
asyncio.run(main())
