DSPark 1.6.1
Header-only audio DSP framework in pure C++20 — zero dependencies
Loading...
Searching...
No Matches
PitchShifter.h File Reference

Phase-vocoder pitch shifter with identity phase locking. More...

#include "../Core/AudioBuffer.h"
#include "../Core/AudioSpec.h"
#include "../Core/DenormalGuard.h"
#include "../Core/DspMath.h"
#include "../Core/FFT.h"
#include "../Core/StateBlob.h"
#include "../Core/WindowFunctions.h"
#include <algorithm>
#include <atomic>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <numbers>
#include <vector>
Include dependency graph for PitchShifter.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  dspark::PitchShifter< T >
 Real-time phase-vocoder pitch shifter (+-12 semitones, stereo-linked). More...
 

Namespaces

namespace  dspark
 Main namespace for the DSPark framework.
 

Detailed Description

Phase-vocoder pitch shifter with identity phase locking.

Time-stretches the signal with a phase vocoder and resamples the stretched stream back to the original duration, shifting pitch by the same ratio. Quality rests on three techniques:

  • Identity phase locking (Laroche & Dolson 1999): spectral peaks are detected each frame and every bin in a peak's region of influence is rotated by the same phase increment as its peak, preserving the vertical phase coherence whose loss causes the classic phase-vocoder "phasiness".
  • Transient phase reset: onsets (energy rising > 6 dB over the tracked envelope) re-initialise synthesis phases to the analysis phases, keeping attacks sharp instead of smeared. Peaks with no history (new partials) are reset individually even without a global onset.
  • Spectral anti-alias cut: shifting up reads the synthesis stream faster, so content above Nyquist/ratio would alias; those bins are tapered to zero in the frequency domain before synthesis.

Architecture (per block, streaming, zero allocation):

input ring -> analysis hop Ra (variable, fractional-accumulator exact) -> FFT -> peak picking & phase propagation (reference channel) -> per-channel rigid phase rotation per region -> IFFT -> overlap-add at fixed synthesis hop Rs = N/4 (exact COLA) -> Catmull-Rom fractional reader at rate ratio -> output

The analysis hop carries a fractional accumulator so the average stretch is exactly Rs/(Rs/ratio) = ratio: tuning is exact for arbitrary ratios, with no cumulative drift. Channels share the reference channel's peak/phase decisions (rigid per-region rotation), which preserves inter-channel phase differences exactly - the stereo image does not wander.

Latency: 2 * fftSize samples (reported by getLatency(), measured exact at unity ratio: reader offset fftSize + fftSize/4 behind the write head plus the fftSize - fftSize/4 window/OLA delay of the analysis-synthesis chain). The dry path of the mix control is delay-compensated to the same value, so partial mixes stay comb-free. Channels beyond the prepared count pass through untouched (and therefore uncompensated).

Threading model: parameter setters/getters are std::atomic based and safe from any thread (non-finite values are ignored); prepare() is setup-thread only (allocates; invalid specs are ignored); reset() belongs to the owner of the stream; getState()/setState() are setup/UI threads.

Dependencies: Core/FFT.h, Core/WindowFunctions.h, Core/AudioSpec.h, Core/AudioBuffer.h, Core/DspMath.h, Core/DenormalGuard.h, Core/StateBlob.h.

Definition in file PitchShifter.h.