A cascade/parallel formant synthesizer, simplified from Klatt (1980). It is pure Lua: a whole utterance renders to a buffer in milliseconds under LuaJIT, so it needs no C.
Input: phoneme events { ph, stress, dur, f0 } and a voice knob table.
Output: a mono sound.buffer at 16 kHz (RATE).
Stages:
HH takes the
neighbouring vowel's formants.rank, the consonant, fixes the formants,
and the transition happens inside the lower-ranked vowel. This is the
Holmes/rsynth scheme. Source amplitudes ramp in about 12 ms and dip at
boundaries. f0 interpolates between segment midpoints.Knobs read here: formant scales every resonator; breath moves voicing
into aspiration; flutter wobbles f0; growl alternates period length
and amplitude, a creaky voice; quantize holds frames in blocks of N;
gain.
| Name | Signature |
|---|---|
| render | render(events, voice, opts) -> buf, info/err |
render(
events,voice,opts) ->buf,info/err
Render phoneme events into a mono 16 kHz sample buffer
With opts.yield_every = N, the render calls
coroutine.yield(done_fraction) every N parameter frames. speech.say_job
uses it to slice a long render. The render state lives in locals, so a
sliced render gives the same bytes as a whole one.