Files
pokemon_pinball_wiki/scripts/build_native_named_sound_aliases.py
2026-07-07 00:25:38 -05:00

94 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""Build confirmed-name aliases for native GodotSpikeBridge sound registrations."""
from __future__ import annotations
import argparse
import csv
import os
import re
from pathlib import Path
def slug(value: str) -> str:
return re.sub(r"[^A-Za-z0-9_]+", "_", value).strip("_") or "sound"
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--sound-manifest", type=Path, default=Path("analysis/radium-image/sound_export_manifest.tsv"))
parser.add_argument("--native-map", type=Path, default=Path("analysis/radium-image/native_sound_id_map.tsv"))
parser.add_argument("--alias-dir", type=Path, default=Path("analysis/radium-image/sounds-native-named"))
parser.add_argument("--out", type=Path, default=Path("analysis/radium-image/native_named_sound_manifest.tsv"))
args = parser.parse_args()
manifest = list(csv.DictReader(args.sound_manifest.open(newline=""), delimiter="\t"))
by_object = {int(row["primary_object_local_id"]): row for row in manifest if row["primary_object_local_id"]}
native_rows = list(csv.DictReader(args.native_map.open(newline=""), delimiter="\t"))
args.alias_dir.mkdir(parents=True, exist_ok=True)
output_rows: list[dict[str, object]] = []
for native in native_rows:
sound_id = int(native["native_sound_id"])
source = by_object.get(sound_id)
if source is None:
continue
source_path = Path(source["wav_path"])
alias_name = (
f"{slug(native['name'])}"
f"__obj{sound_id:04d}"
f"_s{int(source['section8_index']):04d}"
f"_{source['channels']}ch_{source['sample_rate']}hz.wav"
)
alias_path = args.alias_dir / alias_name
if not alias_path.exists():
try:
os.link(source_path, alias_path)
link_type = "hardlink"
except OSError:
alias_path.symlink_to(Path("..") / "sounds" / source_path.name)
link_type = "symlink"
else:
link_type = "existing"
output_rows.append(
{
"name": native["name"],
"native_sound_id": sound_id,
"alias_wav_path": alias_path.as_posix(),
"source_wav_path": source_path.as_posix(),
"section8_index": source["section8_index"],
"duration_seconds": source["duration_seconds"],
"channels": source["channels"],
"sample_rate": source["sample_rate"],
"command_ref_count": source["command_ref_count"],
"register_call_ghidra": native["register_call_ghidra"],
"string_ghidra": native["string_ghidra"],
"link_type": link_type,
}
)
fields = [
"name",
"native_sound_id",
"alias_wav_path",
"source_wav_path",
"section8_index",
"duration_seconds",
"channels",
"sample_rate",
"command_ref_count",
"register_call_ghidra",
"string_ghidra",
"link_type",
]
with args.out.open("w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields, delimiter="\t")
writer.writeheader()
writer.writerows(output_rows)
print(f"wrote {args.out} rows={len(output_rows)} alias_dir={args.alias_dir}")
return 0 if len(output_rows) == len(native_rows) else 1
if __name__ == "__main__":
raise SystemExit(main())