"""Archive the DGX original and prepare a gapless-container loop before Unity import.""" import argparse import hashlib import json from pathlib import Path import shutil import subprocess import imageio_ffmpeg import numpy as np ROOT = Path(__file__).resolve().parents[1] WORK = ROOT / "Tools/output/main_menu_music" DESIGN = ROOT / "Doc/Design/Sound/MainMenu" RATE = 48000 def main(): global WORK, DESIGN parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--work", type=Path, default=WORK) parser.add_argument("--design", type=Path, default=DESIGN) parser.add_argument("--stem", default="CandyCamp_MainMenu") parser.add_argument("--title", default="Candy Camp - Main Menu") parser.add_argument("--crossfade-bars", type=float, default=2.0) parser.add_argument("--target-rms-dbfs", type=float) args = parser.parse_args() WORK, DESIGN = args.work.resolve(), args.design.resolve() if not args.stem.replace("_", "").isalnum(): raise SystemExit("Stem must contain letters, numbers and underscores only") stem = args.stem downloaded = json.loads((WORK / "downloaded.json").read_text(encoding="utf-8")) source = WORK / next(name for name in downloaded.values() if name.endswith(".mp3")) metadata = json.loads(source.with_suffix(".json").read_text(encoding="utf-8")) ffmpeg = imageio_ffmpeg.get_ffmpeg_exe() decoded = subprocess.run( [ffmpeg, "-v", "error", "-i", str(source), "-f", "f32le", "-acodec", "pcm_f32le", "-ar", str(RATE), "-ac", "2", "-"], capture_output=True, check=True, ) pcm = np.frombuffer(decoded.stdout, dtype=" RATE * 30 assert np.max(np.abs(checked)) < 1.0, "Encoded output clips" diffs = np.abs(np.diff(checked, axis=0)) seam_delta = float(np.max(np.abs(checked[-1] - checked[0]))) report = { "date": "2026-10-20", "model": "acestep-v15-xl-sft", "lm_model": "acestep-5Hz-lm-4B", "inference_steps": metadata["inference_steps"], "seed": metadata["seed"], "planned_bpm": metadata["cot_bpm"], "planned_key": metadata["cot_keyscale"], "planned_meter": metadata["cot_timesignature"], "prompt": metadata["caption"], "lyrics": metadata["lyrics"], "source": {"file": stem + "_Source.mp3", "seconds": len(pcm)/RATE, "sample_rate": RATE, "channels": 2, "bitrate": "128 kbps", "sha256": hashlib.sha256(source.read_bytes()).hexdigest()}, "loop": {"asset": "AIClient/Assets/Bundles/Sound/BGM/" + stem + "_Loop.ogg", "seconds": len(checked)/RATE, "sample_rate": RATE, "channels": 2, "bytes": output.stat().st_size, "codec": "Vorbis", "quality": 5, "source_end_seconds": float(end_seconds), "crossfade_seconds": overlap_seconds, "crossfade_planned_bars": args.crossfade_bars, "target_rms_dbfs": args.target_rms_dbfs, "gain_db": float(20*np.log10(gain)), "decoded_peak_dbfs": float(20*np.log10(np.max(np.abs(checked)))), "decoded_rms_dbfs": float(20*np.log10(np.sqrt(np.mean(checked**2)))), "boundary_sample_delta": seam_delta, "internal_sample_delta_p99": float(np.percentile(diffs, 99)), "sha256": hashlib.sha256(output.read_bytes()).hexdigest()}, "verification": {"decode": "passed", "finite_samples": True, "clipping": False, "musical_seam": "Cyclic crossfade applied; human listening review pending", "runtime_playback": "Not wired; resource generation/import only"}, } DESIGN.mkdir(parents=True, exist_ok=True) shutil.copy2(source, DESIGN / (stem + "_Source.mp3")) shutil.copy2(source.with_suffix(".json"), DESIGN / "server_metadata.json") (DESIGN / "generation.json").write_text( json.dumps(report, indent=2, ensure_ascii=False) + "\n", encoding="utf-8" ) print(json.dumps(report["loop"], indent=2)) if __name__ == "__main__": main()