StftPitchShift
STFT based real-time pitch and timbre shifting in C++ and Python
Install / Use
/learn @jurihock/StftPitchShiftREADME
stftPitchShift
stftPitchShift is a Short-Time Fourier Transform (STFT) based pitch and timbre shifting algorithm implementation, originally inspired by the Stephan M. Bernsee's smbPitchShift.cpp.
This repository features two analogical algorithm implementations, C++ and Python. Both contain several function blocks of the same name (but different file extension, of course).
In addition to the basic pitch shifting algorithm, it also features spectral poly pitch shifting and cepstral formant preservation extensions.
Both sources contain a ready-to-use command line tool as well as a library for custom needs. See more details in the build section.
Feel free to check out some demos at stftPitchShiftDemo and the stftPitchShiftPlugin as well.
Modules
<details> <summary><strong>StftPitchShift</strong></summary>The StftPitchShift module provides a full-featured audio processing chain to perform the pitch shifting of a single audio track, based on the built in STFT implementation.
Exclusively in the C++ environment the additional StftPitchShiftCore module can be used to embed this pitch shifting implementation in an existing real-time STFT pipeline.
</details> <details> <summary><strong>Vocoder</strong></summary>The Vocoder module transforms the DFT spectral data according to the original algorithm, which is actually the instantaneous frequency estimation technique. See also further reading for more details.
The particular encode function replaces the input DFT values by the magnitude + j * frequency complex numbers, representing the phase error based frequency estimation in the imaginary part.
The decode function does an inverse transformation back to the original DFT complex numbers, by replacing eventually modified frequency value by the reconstructed phase value.
The Pitcher module performs mono or poly pitch shifting of the encoded DFT frame depending on the specified fractional factors.
</details> <details> <summary><strong>Resampler</strong></summary>The Resampler module provides the linear interpolation routine, to actually perform pitch shifting, based on the Vocoder DFT transform.
The Cepster module estimates a spectral envelope of the DFT magnitude vector, representing the vocal tract resonances. This computation takes place in the cepstral domain by applying a low-pass filter. The cutoff value of the low-pass filter or lifter is the quefrency value to be specified in seconds or milliseconds.
</details> <details> <summary><strong>Normalizer</strong></summary>The Normalizer module optionally performs a RMS normalization right after pitch shifting relative to the original signal to get about the same loudness level. This correction takes place in the frequency domain each DFT frame separately.
</details> <details> <summary><strong>STFT</strong></summary>As the name of this module already implies, it performs the comprehensive STFT analysis and synthesis steps.
</details>Pitch shifting
Mono pitch shifting
Since the Vocoder module transforms the original DFT complex values real + j * imag into magnitude + j * frequency representation, the mono pitch shifting is a comparatively easy task. Both magnitude and frequency vectors are to be resampled according to the desired pitch shifting factor:
- The factor
1means no change. - The factor
<1means downsampling. - The factor
>1means upsampling.
Any fractional resampling factor such as 0.5 requires interpolation. In the simplest case, linear interpolation will be sufficient. Otherwise, bilinear interpolation can also be applied to smooth values between two consecutive STFT hops.
Due to frequency vector alteration, the resampled frequency values needs also be multiplied by the resampling factor.
Poly pitch shifting
In terms of poly pitch shifting, multiple differently resampled magnitude and frequency vectors are to be combined together. For example, the magnitude vectors can easily be averaged. But what about the frequency vectors?
The basic concept of this algorithm extension is to only keep the frequency value of the strongest magnitude value. So the strongest magnitude will mask the weakest one. Thus, all remaining masked components become inaudible.
In this way, the poly pitch shifting can be performed simultaneously in the same DFT frame. There is no need to build a separate STFT pipeline for different pitch variations to superimpose the synthesized signals in the time domain.
Formant preservation
The pitch shifting also causes distortion of the original vocal formants, leading to a so called Mickey Mouse effect if scaled up. One possibility to reduce this artifact, is to exclude the formant feature from the pitch shifting procedure.
The vocal formants are represented by the spectral envelope, which is given by the smoothed DFT mangitude vector. In this implementation, the smoothing of the DFT mangitude vector takes place in the cepstral domain by low-pass liftering. The extracted envelope is then removed from the original DFT magnitude. The remaining residual or excitation signal goes through the pitch shifting algorithm. After that, the previously extracted envelope is combined with the processed residual.
Build
C++
Use CMake to manually build the C++ library, main and example programs like this:
cmake -S . -B build
cmake --build build
Or alternatively just get the packaged library from:
- Vcpkg repository stftpitchshift or
- Ubuntu repository ppa:jurihock/stftpitchshift.
To include this library in your C++ audio project, study the minimal C++ example in the examples folder:
#include <StftPitchShift/StftPitchShift.h>
using namespace stftpitchshift;
StftPitchShift pitchshifter(1024, 256, 44100);
std::vector<float> x(44100);
std::vector<float> y(x.size());
pitchshifter.shiftpitch(x, y, 1);
Optionally specify following CMake options for custom builds:
-DBUILD_SHARED_LIBS=ONto enable a shared library build,-DVCPKG=ONto enable the vcpkg compatible library only build without executables,-DDEB=ONto enable the deb package build for library and main executable,-DWASM=ONto enable the wasm library build used in demo project.
Python
The Python program stftpitchshift can be installed via pip install stftpitchshift.
Also feel free to explore the Python class StftPitchShift in your personal audio project:
from stftpitchshift import StftPitchShift
pitchshifter = StftPitchShift(1024, 256, 44100)
x = [0] * 44100
y = pitchshifter.shiftpitch(x, 1)
Usage
Both programs C++ and Python provides a similar set of command line options:
-h --help print this help
--version print version number
-i --input input .wav file name
-o --output output .wav file name
-p --pitch fractional pitch shifting factors separated by comma
(default 1.0)
-q --quefrency optional formant lifter quefrency in milliseconds
(default 0.0)
-t --timbre fractional timbre shifting factor related to -q
(default 1.0)
-r --rms enable spectral rms normalization
-w --window stft window size
(default 1024)
-v --overlap stft window overlap
(default 32)
-c --chrono enable runtime measurements
(only available in the C++ version)
-d --debug plot spectrograms before and after processing
(only available in the Python version)
Currently only .wav files are supported. Please use e.g. Audacity or SoX to prepare your audio files for pitch shifting.
To apply multiple pitch shifts at once, separate each factor by a comma, e.g. -p 0.5,1,2. Alternatively specify pitch shifting factors as semitones denoted by the + or - prefix, e.g. -p -12,0,+12. For precise pitch corrections append the number of cents after semitones, e.g. -p -11-100,0,+11+100.
To enable the formant preservation feature specify a suitable quefrency value in milliseconds. Depending on the source signal, begin with a small value like -q 1. Generally, the quefrency value has to be smaller than the fundamental period, as reciprocal of the fundamental frequency, of the source signal.
At the moment the
Related Skills
openai-image-gen
330.3kBatch-generate images via OpenAI Images API. Random prompt sampler + `index.html` gallery.
claude-opus-4-5-migration
81.3kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
docs-writer
98.7k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
330.3kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
