The phase-vocoder path is implemented by Resynthesizer (private/src/Resynthesis.hpp) and driven by GrainManager (private/src/DelayLine.hpp) inside the Quad Delay.
The Quad Delay uses a moveable read head in warped time. Without correction, variable read speed causes strong pitch shifts.
The phase vocoder decouples time-stretch from perceived pitch so delay-time warping can happen while keeping spectral pitch stable.
GrainManager::Process() launches a new grain every Resynthesizer::GetGrainLaunchSamples() samples, i.e. every hop H = N / 4 (x_hopDenom = 4).
For each launched grain:
startTime).startTime - H.Grain::Start(...).Resynthesizer::PrimeAnalysis(previousWaveTable) stores previous bin phases/magnitudes.DFT::Transform(buffer)ProcessPhases() computes:
m_analysisMagnitudes[bin]m_analysisPhase[bin]m_omegaInstantaneous[bin] via phase-deviation formula:
omega_bin * Homega_binPVDR::Analyze() builds leader/follower bin relationships.Oscillator::FixupPhases(detune, pvdr) advances synthesis phase per PVDR result.Oscillator::Synthesize(...) writes complex bins with shift/unison gains.InverseTransform(...) creates the grain waveform and grain->Start() schedules playback.This is the “phase vocoder done right” principle in practice: phase propagation is controlled by measured inter-frame phase advance, not by naive phase reuse.
PVDR is the core phase-relationship tracker that prevents incoherent bin drift.
PriorityQueue<Entry,...> over current and previous analysis magnitudes).PVDR::Result:
m_bin: current binm_parent: leader bin this bin followsm_delta: phase increment to apply from parentm_small: low-energy/randomized handling flagbin == parent), usually using omega_instantaneous * H.PushResult() recursively flattens ancestry so each result references a stable root parent.During synthesis:
FixupPhases() walks PVDR results and updates m_synthesisPhase[bin].Each grain is synthesized by 3 oscillators (x_numOscillators = 3), each maintaining its own m_synthesisPhase[].
For each oscillator, Synthesize() mixes two shift layers (Oscillator::x_numShifts = 2):
Q(1,1))input.m_shift[0])m_fade[0] with curve fade^4:
gainA = 1 - fade^4gainB = fade^4Per-bin magnitude source is m_synthesisMagnitudes[bin].m_output, which is slewed to reduce abrupt spectral jumps.
Pitch shift is ratio-based (Q rational values), selected upstream in QuadDelayInputSetter from musical intervals.
Oscillator::SynthesizeSingleShift():
1/1, bins are synthesized directly.BinOmega(omega_instantaneous * shift)synthesisPhase * shifttargetFollower = targetParent - parent + binphaseFollower = phaseParent + deltaWillAlias(...) rejects bins where frequency mismatch exceeds threshold (0.5 / H criterion).So the shift is not “bin-by-bin naive remap”; it preserves PVDR structural relationships where possible.
Unison is implemented as 3-oscillator energy-distributed layering:
1.0m_unisonDetune1.0 / m_unisonDetuneGetUnisonGainForOscillator()):
sqrt(1 - 2 * u^2 / 3)u / sqrt(3)
where u = m_unisonGain.This keeps output level controlled while adding symmetric spread.
In addition, delay modulation can inject per-channel sample offsets (sampleOffset) before analysis grain capture, which contributes to stereo/quad width and motion.
From QuadDelayInputSetter into Resynthesizer::Input:
m_shift[0]: musical pitch ratiom_fade[0]: blend between dry spectral map and shifted spectral mapm_unisonDetune, m_unisonGainm_slewUp: partial rise-rate control for spectral bloomm_slewDown exists in the input struct but the active code path currently applies SetSlewUp(...) during grain start.
In the delay path:
QuadDelayInputSetter computes warped read head positions.QuadGrainManager launches grains at those positions.Resynthesizer performs phase-coherent reconstruction.This enables:
Q ratios)