Pitch Shifter
Tier: Primitives | ComponentType: 15 | Params: 4
Granular time-domain pitch shifter using Hann-windowed dual-grain crossfade.
Overview
PitchShifter changes the pitch of incoming audio without changing its speed, using a granular time-domain approach. Two overlapping grains, each windowed with a Hann envelope, read from a circular buffer at a rate determined by the pitch shift amount. The half-grain offset between the two grains ensures a smooth crossfade with no discontinuities.
Shift is specified in semitones with an additional fine detune in cents. Grain size controls the trade-off between tonal quality (larger grains, better for sustained notes) and transient response (smaller grains, better for drums).
File Locations
| Path | |
|---|---|
| Header | Sources/FolioDSP/include/FolioDSP/Primitives/PitchShifter.h |
| Implementation | Sources/FolioDSP/src/Primitives/PitchShifter.cpp |
| Tests | Tests/FolioDSPTests/PitchShifterTests.swift |
| Bridge | Sources/FolioDSPBridge/src/FolioDSPBridge.mm (PitchShifterBridge) |
Parameters
| Index | Name | Description | Min | Max | Default Min | Default Max | Default | Unit |
|---|---|---|---|---|---|---|---|---|
| 0 | Shift | Pitch shift amount in semitones | -24.0 | 24.0 | -12.0 | 12.0 | 0.0 | st |
| 1 | Grain Size | Window size for each grain | 1.0 | 200.0 | 5.0 | 50.0 | 20.0 | ms |
| 2 | Mix | Dry/wet blend | 0.0 | 100.0 | 0.0 | 100.0 | 100.0 | % |
| 3 | Detune | Fine pitch offset in cents | -100.0 | 100.0 | -50.0 | 50.0 | 0.0 | ct |
Processing Algorithm
1. Playback Rate
where \(s\) = shift (semitones), \(d\) = detune (cents). +12 st → rate 2.0 (octave up), -12 st → rate 0.5 (octave down).
2. Write to Circular Buffer
Input is written to an 88200-sample circular buffer at the write pointer.
3. Dual Grain Readout
Two grains read from the buffer, offset by half a grain period:
where \(G\) = grain size in samples, \(\phi\) = grain phase (0–1).
4. Hann Window Crossfade
5. Dry/Wet Mix
Snapshot Fields
| Field | Type | Range | Unit | Description |
|---|---|---|---|---|
| Shift | Float | -24–24 | st | Current pitch shift |
| Detune | Float | -100–100 | ct | Fine detune |
| Grain Size | Float | 1–200 | ms | Current grain window |
| Input | Float | 0–1 | Input level | |
| Output | Float | 0–1 | Output level | |
| Rate | Float | 0.25–4 | x | Playback rate multiplier |
Implementation Notes
- 88200-sample circular buffer (2 seconds at 44.1 kHz)
- Two overlapping grains with half-period offset eliminate crossfade artifacts
- Hann window provides smooth amplitude envelope (zero at edges, peak at center)
- Minimum grain size clamped to 64 samples to prevent aliasing
- Linear interpolation on buffer reads for sub-sample accuracy
Equation Summary
y = Σ grain[pos·2^(st/12)] · hann(env)