A Conditional Flow Matching (CFM) model with a Diffusion Transformer (DiT) backbone for generating natural Yoruba speech from text. The model operates in the continuous latent space of Meta's EnCodec audio codec, learning to transform Gaussian noise into speech latents conditioned on phoneme sequences.
Quick Start
python
1from transformers import AutoModel
2from IPython.display import Audio
34model = AutoModel.from_pretrained(5"FloatinggOnion/yoruba-cfm-dit",6 trust_remote_code=True,7)89output = model.generate("Bawo ni, ẹ kú àárọ̀.")1011# Play in a notebook12Audio(output["audio"].squeeze().cpu().numpy(), rate=output["sample_rate"])
Text Encoder -- A 4-layer Transformer encoder that converts Yoruba phoneme sequences (produced by YorubaG2P) into conditioning embeddings.
Diffusion Transformer (DiT) -- 10 DiT blocks with self-attention over the latent sequence and cross-attention to the text conditioning. Sinusoidal timestep embeddings are injected via an MLP.
EnCodec Decoder -- Meta's pretrained EnCodec 24kHz decoder converts the generated continuous latents back into a 24kHz audio waveform.
Conditional Flow Matching
Instead of the standard diffusion denoising objective, this model uses Conditional Flow Matching (CFM) with a linear interpolation path:
Forward process: x_t = (1 - t) * x_0 + t * x_1 where x_0 ~ N(0, I) and x_1 is the target audio latent
The model learns to predict the velocity field v = x_1 - x_0
At inference, an ODE solver (Euler method, 24 steps) integrates from noise to data
This approach is simpler and more stable than score-based diffusion, and allows fast generation with few sampling steps.
The released weights are the Exponential Moving Average (EMA) of the model parameters, which produces more stable and higher-quality outputs than the raw training weights.
Pre-encoded Latents
Audio from the training dataset was pre-encoded into continuous EnCodec latents (shape [T, 128] per sample) and stored as .pt files. These are available at FloatinggOnion/yoruba-cfm-latents.
Finetuning
You can finetune this model on additional Yoruba speech data:
python
1from transformers import AutoModel
2import copy, torch
34# Load pretrained5pretrained = AutoModel.from_pretrained("FloatinggOnion/yoruba-cfm-dit", trust_remote_code=True)6cfm_model = pretrained.cfm.to("cuda")78# Set up EMA9ema_model = copy.deepcopy(cfm_model).eval()10for p in ema_model.parameters():11 p.requires_grad =False1213# Train with lower LR14optimizer = torch.optim.AdamW(cfm_model.parameters(), lr=5e-5, betas=(0.9,0.95))1516for batch in your_dataloader:17 loss = cfm_loss(cfm_model, batch)# same CFM loss function18 loss.backward()19 optimizer.step()20 optimizer.zero_grad()2122# Update EMA23with torch.no_grad():24for ep, mp inzip(ema_model.parameters(), cfm_model.parameters()):25 ep.mul_(0.999).add_(mp, alpha=0.001)2627# Save finetuned model28pretrained.cfm.load_state_dict(ema_model.state_dict())29pretrained.save_pretrained("./finetuned-yoruba-cfm")
New data must be encoded with the same EnCodec model (facebook/encodec_24khz) and phonemized with YorubaG2P using the same vocabulary. See the training notebook for the full data preparation and finetuning pipeline.
generate() API
python
1output = model.generate(2 text="Bawo ni",# Raw Yoruba text (uses YorubaG2P internally)3# phoneme_ids=tensor, # Or pass pre-computed phoneme IDs [1, L]4 num_latent_frames=150,# Target duration in EnCodec frames (default: 150)5 num_ode_steps=24,# ODE solver steps (default: 24, higher = better quality)6)78output["audio"]# torch.Tensor -- waveform9output["sample_rate"]# int -- 24000
Text input requires yoruba-g2p (pip install yoruba-g2p). Pass phoneme_ids directly to skip this dependency.
Dependencies
torch>=2.4
transformers>=4.40
safetensors
huggingface_hub
yoruba-g2p # for text input (optional if passing phoneme_ids)
epitran # required by yoruba-g2p
Files in This Repository
File
Description
config.json
Model configuration (hyperparameters, auto_map)
model.safetensors
Pretrained EMA weights (safetensors format)
phoneme_vocab.json
Phoneme-to-ID mapping (67 tokens)
modeling_yoruba_cfm.py
Model implementation (YorubaCFMForTTS)
configuration_yoruba_cfm.py
Config class (YorubaCFMConfig)
yoruba_cfm_ema_weights.pt
Legacy EMA weights (raw PyTorch format)
yoruba_cfm_last.ckpt
Legacy Lightning checkpoint
Limitations
Trained on a single speaker dataset; voice diversity is limited
No explicit duration or prosody control
Audio quality depends on the EnCodec decoder, which can introduce artifacts at boundaries
The model generates a fixed number of latent frames; very short or very long utterances may have silence or truncation
Audio encoding and decoding uses Meta's EnCodec neural audio codec:
bibtex
1@article{defossez2022encodec,
2 title={High Fidelity Neural Audio Compression},
3 author={D{\'e}fossez, Alexandre and Copet, Jade and Synnaeve, Gabriel and Adi, Yossi},
4 journal={arXiv preprint arXiv:2210.13438},
5 year={2022}
6}
Conditional Flow Matching
The training objective is based on Flow Matching for Generative Modeling:
bibtex
1@article{lipman2023flow,
2 title={Flow Matching for Generative Modeling},
3 author={Lipman, Yoel and Chen, Ricky T. Q. and Ben-Hamu, Heli and Nickel, Maximilian},
4 journal={arXiv preprint arXiv:2210.02747},
5 year={2023}
6}
YorubaG2P
Text-to-phoneme conversion uses the yoruba-g2p library for Yoruba grapheme-to-phoneme conversion.