CoolFace
Datasetpublic

simpra/xh-tts-slr32-norm

isiXhosa TTS — SLR32 prepared for VITS Multi-speaker isiXhosa speech, resampled and text-normalised for VITS training. Each audio file is paired with its transcript in metadata.csv. Attribution (required by the licence) Derived from OpenSLR SLR32, "High quality TTS data for four South African languages (af, st, tn, xh)", created by North West University and Google (2017), released under CC BY-SA 4.0. Source: https://openslr.org/32/ This derivative is likewise CC… See the full description on the dataset page: https://huggingface.co/datasets/simpra/xh-tts-slr32-norm.

sourceHugging Facecc-by-sa-4.0updated 14d agoView on Hugging Face
0likes124downloads
Dataset Card

isiXhosa TTS — SLR32 prepared for VITS

Multi-speaker isiXhosa speech, resampled and text-normalised for VITS training. Each audio file is paired with its transcript in metadata.csv.

Attribution (required by the licence)

Derived from OpenSLR SLR32, "High quality TTS data for four South African languages (af, st, tn, xh)", created by North West University and Google (2017), released under CC BY-SA 4.0.

  • —Source: https://openslr.org/32/
  • —This derivative is likewise CC BY-SA 4.0. Anything you distribute that is a derivative of it — including, arguably, model weights trained on it — is subject to ShareAlike. Decide whether that is acceptable before building a closed product on top of it.

Contents

pathwhat
wavs/2,161 utterances, 22,050 Hz mono 16-bit
metadata.csvfile_name, transcription, speaker_id, speaker — HF AudioFolder format
xh_audio_sid_text_train_filelist.txtVITS format `path\speaker_id\text`, 2,137 rows
xh_audio_sid_text_val_filelist.txtsame, 24 rows (2 per speaker)
speakers.jsonspeaker string → contiguous id
config_xhosa.jsonVITS config, validated against vctk_base.json

Measured properties

audio2.61 h (from 3.11 h before filtering), 22,050 Hz mono
utterances2,161 (from 2,420)
speakers12, ids 0–11
utterance lengthmedian ~4.3 s, 98.9% within 1–11 s
symbol set37: _;:,.!?'"- + a–z

Speaker pitch (measured, autocorrelation median F0)

idspeakermedian F0reads as
54291149 Hzmale candidate (only 7.4 min)
86975162 Hzambiguous
0,1,2,3,4,6,7,9,10,11—176–218 Hzfemale

This corpus is effectively female-only. The single male candidate has 7.4 minutes, which cannot carry a voice. To get a male default voice, add your own recordings as an additional speaker id and let the multi-speaker embedding separate timbre from the Xhosa phonology learned here.

What was changed from the source

  1. 1.Resampled 48,000 → 22,050 Hz using scipy.signal.resample_poly (exactly 147/320, so no approximation).
  2. 2.Transcripts normalised by xhosa_text.xhosa_cleaners: NFKC, curly punctuation folded to ASCII, é→e (×4) and ć→c (×1), lowercased, whitespace collapsed, characters outside the symbol set removed.
  3. 3.259 utterances dropped (29.5 min) — every one containing digits. isiXhosa numerals take a concord prefix agreeing with noun class (ezi-25, ayi-9, asi-8), so expanding them needs a native speaker rather than a guess. The 66 distinct values are listed in numbers_xh.json upstream; fill them in and re-run prep to recover that audio.
  4. 4.English utterances kept. ~11% of the source is English read by the same Xhosa speakers (a collection artefact — several are from Jack London's Call of the Wild). They are real human audio, correctly transcribed, and code-switched English is realistic in South African speech.

Why no IPA click symbols

isiXhosa orthography writes its clicks as the plain letters c, q, x plus digraphs (ch, gc, nc, ngq, xh, gx, nx…). Measured across these transcripts and 15.5M characters of other Xhosa text, the letter inventory is exactly ASCII a–z. The IPA click characters ǀ ǃ ǁ ǂ do not occur and must not be in the symbol set — this is a grapheme model.

Training

Copy xhosa_text.py into the VITS repo as text/xhosa.py, then:

python
# text/symbols.py
from text.xhosa import symbols

# text/cleaners.py
from text.xhosa import xhosa_cleaners
bash
python train_ms.py -c config_xhosa.json -m xhosa_vits   # train_ms = multi-speaker

n_speakers is 12 and gin_channels is 256; both are required for the multi-speaker path. cleaned_text is true because the text here is already normalised — the loader must not clean it a second time.

Inference

python
sid = torch.LongTensor([5])            # which of the 12 voices
audio = net_g.infer(x, x_lengths, sid=sid, noise_scale=.667,
                    noise_scale_w=0.8, length_scale=1.0)[0][0,0].data.cpu().float().numpy()

length_scale controls speed (higher is slower).