94 lines
3.5 KiB
Python
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())
|