Download code/eval/build_asr_eval.py from Modularcomputing/dynamic-accent-duplex: direct link, hf CLI and curl.
- Browser
- Download file 2.9 kB
-
https://huggingface.co/Modularcomputing/dynamic-accent-duplex/resolve/main/code/eval/build_asr_eval.py
- Command line
-
hf download hf://Modularcomputing/dynamic-accent-duplex/code/eval/build_asr_eval.py
-
curl -L -o build_asr_eval.py https://huggingface.co/Modularcomputing/dynamic-accent-duplex/resolve/main/code/eval/build_asr_eval.py
2.9 kB
| """Build held-out ASR/LID eval set -> /scratch/duplex/asr_eval/{wav/*.wav, list.jsonl} | |
| Mono: WAXAL test (ibo/yor/hau/pcm, 40 each, spread over speakers), FLEURS val eng (30). | |
| CS: 40 synthetic code-switched clips = two held-out clips of different languages concatenated (0.25 s gap), ref = joined text + per-word lang labels. | |
| All splits are test/val/dev splits never used in TTS training; whether the ASR models saw them is unknown (noted in report).""" | |
| import json, os, random, numpy as np, soundfile as sf, librosa | |
| H = os.path.expanduser("~"); OUT = "/scratch/duplex/asr_eval"; os.makedirs(OUT + "/wav", exist_ok=True) | |
| random.seed(7) | |
| def rows(d, pred): | |
| R = [json.loads(l) for l in open(f"{d}/meta.jsonl")] | |
| return [r for r in R if pred(r)] | |
| def audio(d, r): | |
| a = np.memmap(f"{d}/pcm24k.i16", dtype=np.int16, mode="r") | |
| y = a[r["off24"]: r["off24"] + r["n24"]].astype(np.float32) / 32768 | |
| return librosa.resample(y, orig_sr=24000, target_sr=16000) | |
| def pick(R, n): | |
| by = {} | |
| for r in R: by.setdefault(r.get("spk"), []).append(r) | |
| for v in by.values(): random.shuffle(v) | |
| out = [] | |
| while len(out) < n and any(by.values()): | |
| for k in list(by): | |
| if by[k] and len(out) < n: out.append(by[k].pop()) | |
| return out | |
| items = [] | |
| W = f"{H}/data3/waxal" | |
| for L in ["ibo", "yor", "hau", "pcm"]: | |
| for r in pick(rows(W, lambda r: r["lang"] == L and r["split"] == "test" and 1.5 < r["dur"] < 14), 40): | |
| items.append(("waxal_test", W, r, L)) | |
| F = f"{H}/data3/fleurs" | |
| for r in pick(rows(F, lambda r: r["lang"] == "eng" and r["split"] == "val" and r["dur"] < 16), 30): items.append(("fleurs_val", F, r, "eng")) | |
| recs = []; pool = {} | |
| for src, d, r, L in items: | |
| y = audio(d, r); i = f"{L}_{len(recs):03d}" | |
| sf.write(f"{OUT}/wav/{i}.wav", y, 16000) | |
| rec = dict(id=i, wav=f"{OUT}/wav/{i}.wav", lang=L, text=r["text"], src=f"{src}:{r['id']}", dur=round(len(y) / 16000, 2), | |
| wlang=[L] * len(r["text"].split())) | |
| recs.append(rec); pool.setdefault(L, []).append((rec, y)) | |
| pairs = [("eng", "ibo"), ("ibo", "eng"), ("eng", "yor"), ("yor", "eng"), ("eng", "hau"), ("hau", "eng"), ("pcm", "eng"), ("eng", "pcm"), ("pcm", "ibo"), ("pcm", "yor")] | |
| for k in range(40): | |
| a, b = pairs[k % len(pairs)] | |
| (ra, ya), (rb, yb) = random.choice(pool[a]), random.choice(pool[b]) | |
| y = np.concatenate([ya, np.zeros(4000, np.float32), yb]); i = f"cs_{k:03d}" | |
| sf.write(f"{OUT}/wav/{i}.wav", y, 16000) | |
| recs.append(dict(id=i, wav=f"{OUT}/wav/{i}.wav", lang="cs", langs=[a, b], text=ra["text"] + " " + rb["text"], src=f"concat:{ra['id']}+{rb['id']}", | |
| dur=round(len(y) / 16000, 2), wlang=ra["wlang"] + rb["wlang"])) | |
| with open(f"{OUT}/list.jsonl", "w") as f: | |
| for r in recs: f.write(json.dumps(r, ensure_ascii=False) + "\n") | |
| from collections import Counter; print(Counter(r["lang"] for r in recs)); print("BUILD_DONE", len(recs)) | |