Views
No views yet
Text -> CharEncoder (4x Conv1d) -> DurationPredictor (2x Conv1d, detached)
-> LengthRegulator (repeat by durations)
-> FrameDecoder (3x Conv1d) -> [F0, RMS]1import torch
2from model_prosody import ProsodyPredictor
3from infer_prosody import predict_prosody
4
5ckpt = torch.load("final_model.pt", map_location="cpu", weights_only=False)
6model = ProsodyPredictor(vocab_size=ckpt["vocab_size"], d_model=128, dropout=0.0)
7model.load_state_dict(ckpt["model"])
8model.eval()
9
10result = predict_prosody("Hello, I am Kobi AI", model, ckpt["norm_stats"])
11# result["f0_hz"] - pitch in Hz per 100ms frame
12# result["rms"] - volume per 100ms frame
13# result["duration_s"] - total duration in seconds1import numpy as np
2import soundfile as sf
3from scipy.interpolate import CubicSpline
4
5f0 = result["f0_hz"]
6rms = result["rms"]
7sr = 24000
8frame_dur = 0.1
9n_frames = len(f0)
10total_samples = int(n_frames * frame_dur * sr)
11
12# Smooth interpolation between frames
13frame_times = (np.arange(n_frames) + 0.5) * frame_dur
14sample_times = np.arange(total_samples) / sr
15f0_smooth = np.clip(CubicSpline(frame_times, f0, bc_type='clamped')(sample_times), 50, 300)
16rms_smooth = np.clip(CubicSpline(frame_times, rms, bc_type='clamped')(sample_times), 0, None)
17
18# Generate with continuous phase
19phase = np.cumsum(2 * np.pi * f0_smooth / sr)
20audio = (rms_smooth * np.sin(phase)).astype(np.float32)
21audio = audio / (np.abs(audio).max() + 1e-8) * 0.8
22sf.write("output.wav", audio, sr)| File | Description |
|---|---|
final_model.pt | Fully trained model (200 epochs, 8000 steps) |
best_model.pt | Best validation checkpoint (val loss 1.078) |
model_prosody.py | Model definition (ProsodyPredictor) |
infer_prosody.py | Inference helper (predict_prosody()) |
extract_features.py | Feature extraction from WAV + text (vocab, tokenizer) |
MSE(pitch, voiced only) + MSE(volume, all frames) + 0.1 * MSE(log duration)