Python synthesizer
A simple virtual analog synthesizer written in Python.
- Oscillators: sine, sawtooth, square (with pulse width), triangle and noise, plus a detunable second oscillator
- ADSR envelope
- Resonant lowpass / highpass / bandpass filter
- LFO for vibrato, tremolo and filter cutoff modulation
- Playback via PyAudio and export to wav files
Installation
pip install synthesizer
To play sounds with Player, install PyAudio as well.
pip install "synthesizer[audio]"
Install dependencies for PyAudio
Ubuntu
apt install portaudio19-dev
macOS
brew install portaudio
Basic usage
Play 440Hz sine wave
Generated waves are NumPy arrays normalized to [-1.0, 1.0].
Available waveforms are Waveform.sine, Waveform.sawtooth, Waveform.square, Waveform.triangle and Waveform.noise.
>>> from synthesizer import Player, Synthesizer, Waveform
>>> player = Player()
>>> player.open_stream()
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sine, osc1_volume=1.0, use_osc2=False)
# Play A4
>>> player.play_wave(synthesizer.generate_constant_wave(440.0, 3.0))
Play chord
# Play C major
>>> chord = ["C3", "E3", "G3"]
>>> player.play_wave(synthesizer.generate_chord(chord, 3.0))
# You can also specify frequencies to play just intonation
>>> chord = [440.0, 550.0, 660.0]
>>> player.play_wave(synthesizer.generate_chord(chord, 3.0))
You can use PyChord to handle chords easily.
>>> from pychord import Chord
>>> chord = Chord("Dm7/G")
>>> player.play_wave(synthesizer.generate_chord(chord.components_with_pitch(root_pitch=3), 3.0))
Noise, pulse width and detune
# White noise (pass seed to make it reproducible)
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.noise, seed=42)
# Square wave with 25% duty cycle
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.square, osc1_pulse_width=0.25)
# Detune oscillator 2 by +7 cents for a thicker sound
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sawtooth, use_osc2=True,
... osc2_waveform=Waveform.sawtooth, osc2_volume=1.0,
... osc2_freq_transpose=1.0, osc2_detune=7.0)
ADSR envelope
Each generated wave fades in and out (10 ms by default) to prevent click noise between notes. The release is included in the length of the wave.
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sine, attack=0.05, release=0.2)
# Disable the envelope
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sine, attack=0.0, release=0.0)
Use decay and sustain for a full ADSR envelope, e.g. a plucked sound.
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sawtooth,
... attack=0.005, decay=0.3, sustain=0.2, release=0.1)
Filter
A resonant 2-pole (12 dB/oct) filter can be applied to the oscillators.
filter_resonance is the Q factor; values above 0.707 emphasize the cutoff frequency.
>>> from synthesizer import FilterType
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sawtooth,
... filter_type=FilterType.lowpass, filter_cutoff=800.0, filter_resonance=4.0)
Available filter types are FilterType.lowpass, FilterType.highpass and FilterType.bandpass.
High resonance may push the wave beyond [-1.0, 1.0]; such samples are clipped when played or written.
LFO
An LFO (low frequency oscillator) can modulate pitch (vibrato), amplitude (tremolo) and filter cutoff. Each depth is 0 (disabled) by default.
# Vibrato of +-30 cents and tremolo at 6 Hz
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.triangle,
... lfo_rate=6.0, lfo_pitch_depth=30.0, lfo_amp_depth=0.4)
# Wah effect: sweep the cutoff +-2 octaves at 2 Hz
>>> synthesizer = Synthesizer(osc1_waveform=Waveform.sawtooth, osc1_volume=0.4,
... filter_type=FilterType.lowpass, filter_cutoff=800.0, filter_resonance=6.0,
... lfo_rate=2.0, lfo_cutoff_depth=2.0)
lfo_waveform accepts any Waveform; Waveform.noise gives a random value per LFO cycle (sample and hold).
Specify audio device
>>> player.enumerate_device()
# index: 00, name: "Built-in Microphone", rate: 44100
# index: 01, name: "Built-in Output", rate: 44100
# index: 02, name: "UA-25EX 44.1kHz", rate: 44100
>>> player.open_stream(device_name="UA-25EX")
Player can also be used as a context manager, which closes the stream and releases PyAudio resources on exit.
>>> with Player() as player:
... player.open_stream()
... player.play_wave(synthesizer.generate_constant_wave("A4", 1.0))
Write wav file
>>> from synthesizer import Writer
>>> writer = Writer()
>>> chord = ["C4", "E4", "G4"]
>>> wave = synthesizer.generate_chord(chord, 3.0)
>>> writer.write_wave("path/to/your.wav", wave)
# Concatenate multiple waves into a single file
>>> writer.write_waves("path/to/your.wav", wave1, wave2, wave3)
Examples
play_440hz.py
Play 440Hz waves with each waveform and some oscillator combinations.
python example/play_440hz.py
play_chord.py
Play various chords and a chord sequence.
python example/play_chord.py
write_wave.py
Write a chord progression to example/test.wav.
python example/write_wave.py
play_pychord.py
Play chords using PyChord.
pip install "pychord>=0.5.0"
python example/play_pychord.py A C#m7 DM7 Bm7/E A
play_synth_features.py
Play presets using oscillator extensions, ADSR envelope, filter and LFO.
python example/play_synth_features.py
Development
pip install -e ".[test,audio]"
pytest
Supported OS
- macOS
- Linux
Supported versions
- Python 3.10 and above
Author
License
- MIT License
Links
- PyPI: https://pypi.org/project/synthesizer/
- GitHub: https://github.com/yuma-m/synthesizer
- Documentation: https://synthesizer.readthedocs.io
Metadata
Release files for synthesizer 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| synthesizer-0.4.0.tar.gz | 24.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| synthesizer-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.7 kB
Release files / synthesizer-0.4.0.tar.gz
| Download URL | synthesizer-0.4.0.tar.gz |
|---|---|
| Size | 24.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab2a67bbe19af677e577b5901639b837bc09520c47414e4456791ed4a38f7810
|
|
BLAKE2b-256 checksum How to use checksums |
44b0ff0bd10622617cca8491994403e26ca695fb258b60ca38bad25f0818cc7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / synthesizer-0.4.0-py3-none-any.whl
| Download URL | synthesizer-0.4.0-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
251b987930af58b156a2d26365f148b7b0f1ae439122e5d0643695ec9ddd5e26
|
|
BLAKE2b-256 checksum How to use checksums |
b995c2ad7bf9b065e22a84e76716d51fdfcc9cdc707f47585e361ce068e355f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|