Download code/da/data.py from Modularcomputing/dynamic-accent-preview: direct link, hf CLI and curl.
- Browser
- Download file 3.52 kB
-
https://huggingface.co/Modularcomputing/dynamic-accent-preview/resolve/85bc6033c5db6b00b7aac86534c1ca73ceb44fef/code/da/data.py
- Command line
-
hf download hf://Modularcomputing/dynamic-accent-preview@85bc6033c5db6b00b7aac86534c1ca73ceb44fef/code/da/data.py
-
curl -L -o data.py https://huggingface.co/Modularcomputing/dynamic-accent-preview/resolve/85bc6033c5db6b00b7aac86534c1ca73ceb44fef/code/da/data.py
3.52 kB
| """Arm A data: memmapped Vocos mels + byte tokens with per-token language ids; frame-budget bucketing. | |
| Beta-binomial alignment priors are computed in DataLoader workers.""" | |
| import json, os, random | |
| import numpy as np | |
| import torch | |
| from torch.utils.data import Dataset, Sampler | |
| from .text import encode, LANG2ID | |
| from .model import beta_binomial_prior | |
| N_MELS = 100 | |
| def load_meta(root, datasets, split="train", max_frames=1400, max_tokens=420): | |
| items, mm = [], {} | |
| for ds in datasets: | |
| p = f"{root}/{ds}/meta.jsonl" | |
| if not os.path.exists(p) or os.path.getsize(p) == 0: | |
| continue | |
| mm[ds] = np.memmap(f"{root}/{ds}/mels.f16", dtype=np.float16, mode="r").reshape(-1, N_MELS) | |
| for l in open(p, encoding="utf-8"): | |
| m = json.loads(l) | |
| if m["split"] != split or m["nf"] > max_frames: | |
| continue | |
| if len(m["text"].encode("utf-8")) + 2 > max_tokens: | |
| continue | |
| items.append(m) | |
| return items, mm | |
| class TTSData(Dataset): | |
| def __init__(self, items, mm, spk2id): | |
| self.items, self.mm, self.spk2id = items, mm, spk2id | |
| def __len__(self): | |
| return len(self.items) | |
| def __getitem__(self, i): | |
| m = self.items[i] | |
| mel = np.asarray(self.mm[m["ds"]][m["off"]: m["off"] + m["nf"]], dtype=np.float32) | |
| tok, _ = encode(f"<{m['lang']}>{m['text']}</{m['lang']}>") | |
| lang = [LANG2ID[m["lang"]]] * len(tok) | |
| return dict(tok=tok, lang=lang, mel=mel, spk=self.spk2id[m["spk"]], id=m["id"]) | |
| def collate(batch): | |
| B = len(batch) | |
| N = max(len(b["tok"]) for b in batch) | |
| T = max(len(b["mel"]) for b in batch) | |
| tok = torch.zeros(B, N, dtype=torch.long) | |
| lang = torch.zeros(B, N, dtype=torch.long) | |
| mel = torch.zeros(B, T, N_MELS) | |
| prior = torch.full((B, T, N), -1e4) | |
| tl, ml = torch.zeros(B, dtype=torch.long), torch.zeros(B, dtype=torch.long) | |
| for i, b in enumerate(batch): | |
| n, t = len(b["tok"]), len(b["mel"]) | |
| tok[i, :n] = torch.tensor(b["tok"]); lang[i, :n] = torch.tensor(b["lang"]) | |
| mel[i, :t] = torch.from_numpy(b["mel"]); tl[i], ml[i] = n, t | |
| prior[i, :t, :n] = beta_binomial_prior(n, t) | |
| spk = torch.tensor([b["spk"] for b in batch]) | |
| return dict(tok=tok, lang=lang, tlens=tl, mel=mel, mlens=ml, spk=spk, prior=prior) | |
| class FrameBucketSampler(Sampler): | |
| """Batches of similar length under a padded-frame budget; dataset weights by repetition.""" | |
| def __init__(self, items, frame_budget=40000, weights=None, seed=0): | |
| self.items, self.budget, self.seed, self.epoch = items, frame_budget, seed, 0 | |
| self.weights = weights or {} | |
| def _batches(self): | |
| rng = random.Random(self.seed + self.epoch) | |
| idx = [] | |
| for i, m in enumerate(self.items): | |
| w = self.weights.get(m["ds"], 1.0) | |
| idx += [i] * int(w) + ([i] if rng.random() < (w - int(w)) else []) | |
| idx.sort(key=lambda i: self.items[i]["nf"] + rng.random() * 30) | |
| batches, cur, mx = [], [], 0 | |
| for i in idx: | |
| nf = self.items[i]["nf"] | |
| if cur and max(mx, nf) * (len(cur) + 1) > self.budget: | |
| batches.append(cur); cur, mx = [], 0 | |
| cur.append(i); mx = max(mx, nf) | |
| if cur: | |
| batches.append(cur) | |
| rng.shuffle(batches) | |
| return batches | |
| def __iter__(self): | |
| b = self._batches() | |
| self.epoch += 1 | |
| return iter(b) | |
| def __len__(self): | |
| return len(self._batches()) | |