Build with this node

Start with a prompt in Studio, or copy it into your own coding agent.

Ask Studio

@maruaudio/dsp/spectral/voice-shifter is a monophonic TD-PSOLA shifter built for pitch correction. Analysis marks are placed pitch-synchronously, tracked by correlation at sub-sample positions and anchored on the low-passed waveform peak, so output pitch follows the measured mark spacing times the ratio, including the input's own jitter and vibrato. The ratio sets only the spacing of the next synthesis mark and is smoothed per sample. Each grain is resampled by an independent formant factor while its spacing follows the ratio. A fixed latency and a latency-aligned dry path let the output crossfade to dry input while the caller reports unvoiced audio.

Parameters

PathSetterRange as codedDefaultUnit
ratiosetVoiceShifterRatio0.4454 to 2.2449 (±14 semitones); 2 ms smoothing, immediate before the first sample1ratio
voiceShifterSemitonessetVoiceShifterSemitones−14 to +140semitones
voiceShifterFormantSemitonessetVoiceShifterFormantSemitones−12 to +12; 0 keeps the formants0semitones
periodSamplessetVoiceShifterPeriod32 to the instance's maximum period; steers the mark search onlyrate / 220samples
voicedsetVoiceShifterVoiced0 or non-zero; queued when a voicing delay is set0flag
samplessetVoiceShifterVoicingDelay0 to the latency, rounded0samples
modesetVoiceShifterUnvoicedMode0 dry crossfade, 1 hold the shifted signal once voiced0index

Lifecycle

initVoiceShifter(sampleRate, minimumHz) (rate 8 to 384 kHz, floor 40 to 1000 Hz) allocates power-of-two rings sized for the maximum period (ceil(rate / minimumHz), 64 to 1280), the marks, the grain taper and the voicing queue. Then setters, or updateVoiceShifterFromDetector(state, voiced, period) per detector result → voiceShifterTick(state, x) per sample → resetVoiceShifter, which restores runtime state and keeps the controls.

When to use it

Autotune and harmonizer voices, where a detected pitch and a target note give a ratio and the formants should stay with the singer. The Autotune and Harmonizer modules use it.

Limits

  • Mono sample tick. Latency is voiceShifterLatencySamples, 2.5 maximum periods (1719 samples at 48 kHz for the 70 Hz floor), fixed for the instance.
  • The ratio and formant at a tick shape the grain lookahead input samples earlier (1.5 maximum periods plus four).
  • Formant factors above one read faster than real time with no anti-alias filter; the source notes folding above sampleRate / 4 at +12 semitones and a lower level for shorter grains. Octave-down shifts keep TD-PSOLA's grain gaps.
  • The tick allocates nothing, calls no transcendental and loops to compile-time bounds.

Algorithm properties and proofs

No Lean 4 proof is mapped to this node.

Explore proofs alongside performance

Parameters

ParameterTypeSetter
Ratio ratio

Target pitch ratio, clamped to ±14 semitones; smoothed per sample. Before the first sample (fresh or reset) it applies at once, so no instance starts gliding.

floatsetVoiceShifterRatio
Voice shifter semitones voiceShifterSemitonesfloatsetVoiceShifterSemitones
Voice shifter formant semitones voiceShifterFormantSemitones

Formant shift in semitones, clamped to plus or minus 12; 0 preserves formants.

floatsetVoiceShifterFormantSemitones
Period samples periodSamples

Expected analysis period in samples; it steers the mark search only.

floatsetVoiceShifterPeriod
Voiced voiced

Report the input's voicing. With a voicing delay the change is queued and applied that many samples later, so the crossfade meets the audio the detector described rather than audio still inside the latency. A full queue applies its oldest change early rather than dropping one.

floatsetVoiceShifterVoiced
Samples samples

Delay voicing changes by `samples` (0 to the latency). For a detector whose decision describes audio centred `analysisAge` samples before it is reported, `latency - analysisAge` aligns the crossfade with that audio.

floatsetVoiceShifterVoicingDelay
Mode modefloatsetVoiceShifterUnvoicedMode

Ports

  • In ininput · audio · mono
  • Out outoutput · audio · mono

One sample per voiceShifterTick call.

Dependencies

None: this node imports no other node.

Dependents

No other node imports this one.

Used by