@maruaudio/dsp/spectral/pitch-shifter shifts the pitch of a monophonic signal by time-domain pitch-synchronous overlap-add (TD-PSOLA). The input period is a control input, set from a source frequency: pitch detection and voicing policy belong to another DSP node. Analysis marks are placed one period apart, each refined by correlation (normalized by the candidate's energy) within a quarter period of the expected position. Raised-cosine grains two periods wide are taken at the mark nearest each synthesis point and overlap-added every period / ratio samples; the output is the accumulated sum divided by the accumulated window weight.
Parameters
| Path | Setter | Range as coded | Default | Unit |
|---|---|---|---|---|
semitones | setPitchShifterSemitones | −12 to +12, giving a ratio of 0.5 to 2 | ratio 1 | semitones |
frequencyHz | setPitchShifterSourceFrequency | Clamped to sampleRate / 640.. sampleRate / 40; the period is then 40 to 640 samples | 220 | Hz |
Lifecycle
initPitchShifterNode(sampleRate) preallocates two 4096-sample rings, a window sum ring and 64 marks, with the rate bounded to 8 to 192 kHz. Then setters → pitchShifterNodeTick(state, x) per sample → resetPitchShifterNode, which clears the rings and marks and keeps ratio and period. preparePitchShifterNodeSampleRate re-stamps the bounded rate and re-derives the period from the stored source frequency, keeping history. @maru/analysis-pitch-detector can drive the period through updatePitchShifterFromDetector.
When to use it
Transposing a monophonic voice or instrument by up to an octave either way when its pitch is known, from a detector or from the note being played.
Limits
- Mono sample tick with a fixed latency of 1280 samples (
PITCH_SHIFTER_LATENCY_SAMPLES); output is 0 until then. - At most two analyses and four grains per tick, with a 321-lag search and a 640-sample correlation bound, so every loop is bounded.
- The rings are fixed in samples, so the supported source pitch scales with the rate: 75 to 1200 Hz at 48 kHz.
- Where the window weight is below 10⁻⁶ the output is 0. The leaf playground demo notes that low-level or aperiodic input may not track reliably.