stftpitchshift

repository·main·Indexed 41 days ago

https://github.com/jurihock/stftpitchshift

An STFT-based implementation for pitch and timbre shifting available as a C++ library and Python package. It supports mono, poly, and formant-preserving algorithms to avoid the 'Mickey Mouse' effect using cepstral domain low-pass filtering. The tool includes a CLI for processing .wav files with options for fractional pitch factors, semitone/cent notation, quefrency-based formant lifters, and spectral RMS normalization.

Tokens
3.3K
Snippets
9
Records
15
Agent score
50%

What's inside stftpitchshift

  1. How pitch shifting and formant preservation work

    main

    Mono Pitch Shifting

    Mono pitch shifting is achieved by resampling the magnitude and frequency vectors from the Vocoder module.

    • Factor 1: No change.
    • Factor <1: Downsampling.
    • Factor >1: Upsampling.

    Poly Pitch Shifting

    Poly pitch shifting allows multiple pitch variations in a single DFT frame. The algorithm combines multiple resampled vectors by keeping the frequency value of the strongest magnitude value, effectively masking weaker components.

    Formant Preservation

    To avoid the 'Mickey Mouse' effect, the implementation uses cepstral domain low-pass filtering (liftering) to extract a spectral envelope (the vocal tract resonances). This envelope is removed from the magnitude, the residual signal is pitch-shifted, and then the envelope is recombined with the processed residual.

  2. Build the C++ library with CMake

    main

    You can manually build the C++ library, main, and example programs using CMake.

    Available CMake options for custom builds:

    • -DBUILD_SHARED_LIBS=ON: Enable a shared library build.
    • -DVCPKG=ON: Enable a vcpkg-compatible library-only build (without executables).
    • -DDEB=ON: Enable the .deb package build for the library and main executable.
    • -DWASM=ON: Enable the WebAssembly (WASM) library build.
    cmake -S . -B build
    cmake --build build
  3. Configure STFT window and overlap

    main

    You can control the STFT analysis parameters using:

    • --window (-w): Sets the STFT window size. It accepts a comma-separated list of two values representing the window size tuple (e.g., "1024,1024").
    • --overlap (-v): Sets the STFT window overlap (hop rate) as an integer.

    Example: -w "2048,2048" -v 64

  4. Configure formant lifter (quefrency and timbre)

    main

    To adjust the timbre/formant characteristics, use the following flags:

    • --quefrency (-q): Specifies the formant lifter quefrency in milliseconds. This value is internally converted to seconds.
    • --timbre (-t): A fractional timbre shifting factor related to the quefrency. Like the pitch flag, this can be a decimal factor or use semitone/cent notation.

    Example: -q 5.0 -t 1.2

  5. Configure pitch shifting factors

    main

    The --pitch (or -p) flag accepts a comma-separated list of fractional pitch shifting factors.

    Factors can be provided in two ways:

    1. Decimal/Fractional: e.g., 1.5 for a 50% increase.
    2. Semitone/Cent notation: The tool supports semitone and cent notation (e.g., +2 for 2 semitones, or using cent-based strings). The tool parses these into distinct multipliers.

    Example: -p "1.0,2.0" or -p "+2,+3".

  6. Use the stftPitchShift C++ command line tool

    main

    The stftpitchshift command line tool allows for mono and polyphonic pitch shifting using Short-Time Fourier Transform (STFT). The tool processes audio files by reading input data, applying pitch shifting per channel, and writing the result to an output file.

    Basic execution flow:

    1. The tool parses command line arguments via the CLI class.
    2. It reads audio data using IO::read.
    3. It iterates through audio channels, applying StftPitchShift::shiftpitch to each channel.
    4. It clips the output using IO::clip to prevent overflow.
    5. It writes the processed data using IO::write.

    Note: The tool requires both an input and an output file to be specified via command line arguments.

    # Example conceptual usage (actual flags depend on CLI.h definition)
    stftpitchshift -i input.wav -o output.wav --factors 1.5
  7. Use the StftPitchShift class in C++

    main

    To integrate the pitch shifting library into a C++ project, include StftPitchShift.h and use the StftPitchShift class. The constructor takes window_size, hop_size, and sample_rate as arguments. Use the shiftpitch method to process audio buffers.

    #include <StftPitchShift/StftPitchShift.h>
    
    using namespace stftpitchshift;
    
    // Constructor: window_size, hop_size, sample_rate
    StftPitchShift pitchshifter(1024, 256, 44100);
    
    std::vector<float> x(44100);
    std::vector<float> y(x.size());
    
    // shiftpitch(input_buffer, output_buffer, pitch_factor)
    pitchshifter.shiftpitch(x, y, 1);
  8. Use the StftPitchShift class in Python

    main

    The Python API provides a StftPitchShift class for audio processing. The constructor accepts window_size, hop_size, and sample_rate. The shiftpitch method takes an input list/array and a pitch factor, returning the processed signal.

    from stftpitchshift import StftPitchShift
    
    # Constructor: window_size, hop_size, sample_rate
    pitchshifter = StftPitchShift(1024, 256, 44100)
    
    x = [0] * 44100
    # shiftpitch(input_list, pitch_factor)
    y = pitchshifter.shiftpitch(x, 1)
  9. Reference: stftPitchShift Modules

    main

    The project is organized into several functional modules:

    • StftPitchShift: Full-featured audio processing chain for single tracks. (C++ only: StftPitchShiftCore for embedding in real-time pipelines).
    • Vocoder: Transforms DFT spectral data into magnitude + j * frequency representation using instantaneous frequency estimation.
    • Pitcher: Performs mono or poly pitch shifting.
    • Resampler: Provides linear interpolation for pitch shifting.
    • Cepster: Estimates the spectral envelope via low-pass filtering in the cepstral domain using a quefrency value.
    • Normalizer: Performs optional RMS normalization to maintain loudness.
    • STFT: Handles analysis and synthesis steps.
  10. Use the stftpitchshift CLI tool

    main

    Both C++ and Python versions provide a command-line interface for processing .wav files.

    Common CLI Flags:

    • -i, --input: Input .wav file name.
    • -o, --output: Output .wav file name.
    • -p, --pitch: Fractional pitch shifting factors (comma-separated, e.g., 0.5,1,2) or semitones (e.g., -12,0,+12). For precise cents, use -p -11-100. Default is 1.0.
    • -q, --quefrency: 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 (C++ only).
    • -d, --debug: Plot spectrograms before and after processing (Python only).
  11. Use the StftPitchShift class in Python

    main

    The StftPitchShift class is the core engine for performing pitch and timbre shifting. It is initialized with STFT parameters and the sample rate, then used to process audio channels.

    Initialization

    from stftpitchshift import StftPitchShift
    
    # framesize: list of integers (e.g., [1024])
    # hopsize: integer
    # samplerate: integer
    pitchshifter = StftPitchShift(framesize, hopsize, samplerate)

    Shifting Pitch

    Use the shiftpitch method to process audio data. It supports multi-channel audio by iterating through channels.

    Method Signature (Inferred): shiftpitch(audio_channel, factors, quefrency, distortion, normalization)

    • audio_channel: 1D numpy array representing a single audio channel.
    • factors: List of pitch shifting factors.
    • quefrency: Float representing formant lifter quefrency.
    • distortion: Float representing timbre/distortion factor.
    • normalization: Boolean to enable/disable spectral RMS normalization.
    from stftpitchshift import StftPitchShift
    import numpy as np
    
    # Setup
    samplerate = 44100
    framesize = [1024]
    hopsize = 32
    pitchshifter = StftPitchShift(framesize, hopsize, samplerate)
    
    # Audio data (single channel)
    x = np.random.uniform(-1, 1, samplerate)
    
    # Parameters
    factors = [1.5, 0.75]
    quefrency = 0.002  # 2ms
    distortion = 1.0
    normalization = True
    
    # Process
    y = pitchshifter.shiftpitch(x, factors, quefrency, distortion, normalization)