Downloads · 30 days
0
0% of all-time downloads
nhe-ai/BigVGAN_T50_48k_CoreML
BigVGAN_T50_48k_CoreML is a machine learning model from nhe-ai. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
This is a CoreML decoder based on BigVGAN, converting latent tensors into raw audio waveforms at 48 kHz. It is intended to be used as the final decoding stage in a latent-audio pipeline, leveraging the CoreML stuff wi…
Downloads · 30 days
0
0% of all-time downloads
All-time downloads
11
Public
Repo size
523 MB
Likes
0
Public
Click a slice to open those files.
.bin523 MB · 100%
From the Hugging Face model README
This is a CoreML decoder based on BigVGAN, converting latent tensors into raw audio waveforms at 48 kHz. It is intended to be used as the final decoding stage in a latent-audio pipeline, leveraging the CoreML stuff with a significant speed up and stability against ONNX or PyTorch in MPS.
The model was originally designed to decode latents produced by DiffRhythm2. The original PyTorch weights come from: https://huggingface.co/ASLP-lab/DiffRhythm2/blob/main/decoder.bin
While the decoder may work with other compatible latents (haven't tried though), DiffRhythm2 is the reference source.
Tested with DiffRhythm2 FP32 and FP16 (see: https://huggingface.co/qpqpqpqpqpqp/DiffRhythm2_fp16)
import torch, torchaudio
import coremltools as ct
model = ct.models.MLModel("BigVGAN_T50.mlpackage")
audio = model.predict({"latent": latent.cpu()})["clip_0"]
torchaudio.save("output.wav", torch.from_numpy(audio)[None, :], 48000, format="wav")
Base time unit (important)
The CoreML model is exported with a fixed base window of T = 50.
Original bigvgan.decode_audio() does the work internally, so there's no T restriction. The same behavior can be reproduced with ONNX but not in CoreML.
PyTorch Internals (from decoder.json):
In CoreML, this model expects exactly T = 50 per call.
The output length is fixed and non-configurable.
macOS14 minimum deployment target.For latents with T > 50, decoding must be done manually by chunking.
Recommended:
Padding is required for the final chunk if T is not divisible by 50. Extra decoded audio introduced by padding must be trimmed.
Naive overlap causes noticeable gain increase. Zero overlap avoids gain increase but may introduce small boundary artifacts.
Reference decode_latent_coreml() implementation (CoreML)
import numpy as np
def decode_latent_coreml(mlmodel, latent, T=50, overlap=5):
latent = latent.cpu().numpy()
step = T - overlap
up = 9600
hop_audio = step * up
audio_chunks = []
for i in range(0, latent.shape[2], step):
chunk = latent[:, :, i:i+T]
valid_T = chunk.shape[2]
if valid_T < T:
pad = chunk[:, :, -1:]
pad = np.repeat(pad, T - valid_T, axis=2)
chunk = np.concatenate([chunk, pad], axis=2)
audio = mlmodel.predict({"latent": chunk})["clip_0"]
audio_chunks.append(audio.squeeze().astype(np.float32))
if i + T >= latent.shape[2]:
break
L = audio_chunks[0].shape[-1]
overlap_audio = L - hop_audio
fade = 0.5 - 0.5 * np.cos(np.linspace(0, np.pi, overlap_audio))
fade_in = fade
fade_out = 1.0 - fade
out_len = hop_audio * (len(audio_chunks) - 1) + L
out = np.zeros(out_len, dtype=np.float32)
for i, a in enumerate(audio_chunks):
start = i * hop_audio
end = start + L
if i > 0:
a[:overlap_audio] *= fade_in
if i < len(audio_chunks) - 1:
a[-overlap_audio:] *= fade_out
out[start:end] += a
true_len = latent.shape[2] * up
return out[:true_len]
import torch, torchaudio
torchaudio.save(
"output.wav",
torch.from_numpy(audio)[None, :],
48000
)
from pedalboard.io import AudioFile
with AudioFile("output.wav", "w", 48000, 1) as f:
f.write(audio[None, :])
• Fixed input length (T = 50) per CoreML call
• No internal chunking
• Padding + trimming is mandatory for arbitrary-length latents
• No INT8 / quantized variant
• Overlap handling is entirely user-controlled