Python Stretch
Python Stretch is a simple library for pitch shifting and time stretching audio, currently at version 0.3.1. It acts as a wrapper for the Signalsmith Stretch C++ Library, providing high-quality audio manipulation capabilities. The library supports both mono and multichannel audio and integrates seamlessly with NumPy arrays, making it compatible with other audio processing libraries like librosa. It is also utilized as the core method for pitch and time stretching in the popular audiomentations library. The project shows active maintenance with recent PyPI uploads for version 0.3.1 in early 2025.
Warnings
- gotcha Building `python-stretch` from source requires a C++ compiler and CMake. While pre-built wheels are available for most common platforms and Python versions, users needing to build from source on less common environments might face compilation challenges.
- gotcha The library primarily operates on NumPy arrays. Input audio should be provided as a 2D NumPy array with shape (channels, samples). Passing raw Python lists or incorrectly shaped arrays will lead to errors.
- gotcha The quickstart example and common usage patterns rely on `librosa` for audio loading and `soundfile` for saving. These are not strict dependencies of `python-stretch` itself, but are essential for a complete audio processing workflow.
Install
-
pip install python-stretch
Imports
- Signalsmith
import python_stretch as ps stretch_obj = ps.Signalsmith.Stretch()
Quickstart
import numpy as np
import librosa
import soundfile as sf
import python_stretch as ps
# Load an audio example (e.g., from librosa)
audio, sr = librosa.load(librosa.ex('trumpet'), sr=None)
# Assure that 'audio' is a 2D array (channels, samples)
if audio.ndim == 1:
audio = audio[np.newaxis, :]
# Create a Stretch object
stretch = ps.Signalsmith.Stretch()
# Configure using a preset (numChannels, sampleRate)
stretch.preset(audio.shape[0], sr)
# Shift pitch up by one octave (12 semitones)
stretch.setTransposeSemitones(12)
# Stretch time by a factor (e.g., 0.75 for faster playback)
stretch.timeFactor = 0.75
# Process audio
audio_processed = stretch.process(audio)
# Save and listen (requires soundfile)
# sf.write("audio_original.wav", np.squeeze(audio), sr)
# sf.write("audio_processed.wav", np.squeeze(audio_processed), sr)
print(f"Original audio shape: {audio.shape}, sample rate: {sr}")
print(f"Processed audio shape: {audio_processed.shape}")