Summary
SineGen's random initial phase (rand_ini, kokoro/istftnet.py around line 150) has no effect on the output: it perturbs only index 0 of the sample-rate rad_values, and the subsequent F.interpolate(scale_factor=1/300, mode="linear") downsample (with default align_corners=False) never samples that position. The output is bit-identical across RNG seeds.
Repro (~15 lines)
import torch
from kokoro.istftnet import SineGen
sg = SineGen(24000, 300, harmonic_num=8)
f0 = torch.full((1, 300 * 400, 1), 210.0) # 5 s constant F0, nearest-upsampled form
torch.manual_seed(0)
a = sg._f02sine(f0 * torch.arange(1, 10).view(1, 1, -1))
torch.manual_seed(12345)
b = sg._f02sine(f0 * torch.arange(1, 10).view(1, 1, -1))
print((a - b).abs().max().item()) # 0.0
print(torch.equal(a, b)) # True
Why it matters
- The comment and code suggest harmonics 2..9 are meant to start at random phases; in practice they all start phase-locked at zero, so the intended decorrelation never happens. Whatever the original design intent was (it is inherited from the upstream NSF implementation), the current code does not do it.
- It consumes an RNG draw, which makes the source appear nondeterministic-by-design when the actual nondeterminism comes only from the noise branch.
Two reasonable resolutions: delete the dead code (simplest; output provably unchanged), or move the perturbation after the downsample if random initial phases are actually desired (this would change existing outputs).
Related: #353 adds an opt-in exact integer-phase source; the fix there sidesteps this code path entirely, but the dead code in the default path seems worth cleaning up either way.
🤖 Generated with Claude Code
Summary
SineGen's random initial phase (rand_ini,kokoro/istftnet.pyaround line 150) has no effect on the output: it perturbs only index 0 of the sample-raterad_values, and the subsequentF.interpolate(scale_factor=1/300, mode="linear")downsample (with defaultalign_corners=False) never samples that position. The output is bit-identical across RNG seeds.Repro (~15 lines)
Why it matters
Two reasonable resolutions: delete the dead code (simplest; output provably unchanged), or move the perturbation after the downsample if random initial phases are actually desired (this would change existing outputs).
Related: #353 adds an opt-in exact integer-phase source; the fix there sidesteps this code path entirely, but the dead code in the default path seems worth cleaning up either way.
🤖 Generated with Claude Code