PySynth

Downloads | Changes | Synthesizer modules | Support scripts | Usage | License | Contact

PySynth is a suite of simple music synthesizers and helper scripts written in Python 3. It is based on a synth script I found on the Web and then modified for my purposes. The goal is not to produce many different sounds, but to have scripts that can turn ABC notation or MIDI files into a WAV file without too much tinkering.

There are nine PySynth variants now: PySynth A, the oldest variant, only needs Python itself, and sounds somewhat like a cross between a flute and organ. PySynth B is more complex in sound and needs NumPy. It is supposed to be a little closer to a piano. No competition for Pianoteq of course, but a reasonable fit for keyboard music. PySynth E is similar, but an FM-synthesized e-piano so it sounds much brighter than B (slightly DX7 e-piano-like; I used the DX7 presets in hexter as a basis). PySynth S is more comparable to a guitar, banjo, or harpsichord, depending on note length and pitch. PySynth C, D, and P are subtractive synths, reminiscent of 1970s analog synthesizer voices.

The synthesizers are all monophonic, i.e. they can only play one note at a time. (Although successive notes can overlap in PySynth B and S, but not A.) However, two or more output files can be mixed together as in the case of the stereo files below.

If you need more powerful Python sound synthesis than PySynth offers, you might want to check out the Pyo toolkit. To convert complex ABC files to MIDI and synthesize them, you might want to try abcmidi and Yoshimi respectively.


Audio samples

Here are some WAV output files converted to MP3 or MP4 format:

Mono

Stereo


Download a stable release

Here are tar.gz archives of all PySynth modules:

 
PySynth-2.3.tar.gz (2017-06-30; for Python 3)
PySynth-1.1.tar.gz (2015-01-03; final version for Python 2)

Download the git version

You can browse the repository at GitHub or obtain the source code with git like this:
  git clone git://github.com/mdoege/PySynth.git

ZIP file of the latest git version of PySynth

Arch Linux package (git version)

AUR package


Changes

V2.3 fixes a timing bug in the MIDI file reader.

V2.2 adds a sample-based synth, PySynth “samp”, based on the Salamander piano samples.

V2.1 adds three subtractive synths: “C” (sawtooth wave), “D” (square wave), and “P” (white noise). Also, readmidi.py was improved to better deal with overlapping notes and notes that are switched off by setting their velocity to zero. MIDI rendering seems to work quite well now, as evidenced by the new Popcorn demo song.

V2.0 switches to Python 3, adds the MIDI reader readmidi.py, and incorporates several pull requests with bug fixes and improvements.

V1.1 adds the “E” FM synth module and mixfiles.py.

V1.0.1 fixes a minor issue with Pyglet sound playback and corrects the import path for PyAudio. Thanks again, Pranav!

V1.0 added interactive song creation and playback via menv.py. This CLI allows you to enter notes and hear them played back as synthesized by PySynth. Thanks, Pranav!

V0.9 introduced a Nokia ringtone synthesizer module, contributed by Pēteris Caune. (Run nokiacomposer2wav.py to generate some audio samples.) Thanks, Pete!

V0.8: Improved support for ABC notation features such as tuplets and song tempo; better performance and sound of PySynth “S”.

V0.7: Added the ABC parser and the “B” and “S” synths.

V0.6: Initial public release


Synthesizer modules

These modules take a list of notes and note lengths and use it to create a WAV file. The B, E, and S synths also require NumPy.

PySynth “A”

This additive monophonic synth is very simple and sounds vaguely like a flute or organ, combined with piano-like note volume decay. Only Python itself is needed for PySynth A. It should run on all Python-supported platforms, like Windows, Unix, and the Mac.

PySynth “B”

An additive synth module which attempts to create a more piano-like sound with more harmonics. This version is polyphonic in the sense that it doesn’t cut off previous notes when the next note sounds.

PySynth “C”

PySynth C is a simple bowed string sound based on subtractive synthesis. It uses a sawtooth oscillator and a low-pass filter, similar to a 1970s analog synth (or a string sound in amsynth, or a sound from a MOS Technology SID). Like PySynth A, it only requires Python itself to run.

PySynth “D”

PySynth D uses subtractive synthesis like PySynth C, but is based on a square wave instead. This synth lead-type sound is reminiscent of a woodwind. Square waves were also used in 1970s/1980s computer sound chips such as the General Instrument AY-3-8910 or the Atari POKEY. Only Python itself is required.

PySynth “E”

Based on PySynth B, this module creates a simple e-piano sound based on phase modulation, the usual method of doing FM synthesis e.g. on 1980s Yamaha synthesizers. This sound is of course inspired by the Rhodes piano on a Yamaha DX7.

PySynth “P”

PySynth P uses subtractive synthesis like PySynth C and D, but is based on white noise with an exponential volume envelope. It creates an untuned percussion sound. This type of sound was commonly used in the 1980s for percussive and game sound effects. Only Python itself is required.

PySynth “S”

This module simulates a single plucked string with the Karplus-Strong algorithm (think guitar or harpsichord). Due to the nature of this kind of synthesis, higher frequency-notes in particular can be slightly out of tune with PySynth S, as opposed to the other variants where the harmonics are exact. This could be remedied with a higher sampling rate, but that would also make it a little slow for Python.

PySynth beeper

This contributed synth belongs to nokiacomposer2wav.py and is supposed to recreate ringtones of vintage Nokia feature phones.

PySynth “samp”

This synth uses the 48 kHz, 24-bit Salamander piano samples. Please set the path to the Salamander WAVs (including the trailing slash) on line 50.


Controller & support scripts

These scripts serve as more convenient ways to drive the actual synthesizers.

ABC parser

PySynth has some basic support for music in the ABC notation language. The script needs the location of the ABC song file (either local or via http), optionally followed by the song number (defaults to 1):

python3 read_abc.py http://mdoege.github.io/PySynth/LiliMarlen.abc.txt

Lili Marleen.mp4

Detailed usage:

read_abc.py filename [num_song] [--syn_b/--syn_c/--syn_d/--syn_e/--syn_p/--syn_s/--syn_samp]

* num_song selects the song in the file corresponding to the number given
* --syn_b, --syn_e, --syn_s, etc. can be added to use other PySynth
    modules instead of the default PySynth A

If you need a quick way to edit, visualize, and—in supported browsers—play an ABC music file, take a look at ABCPig.

MIDI reader

Synthesize one track from a MIDI file with PySynth (defaults to MIDI track 1):

python3 readmidi.py file.mid [tracknum] [file.wav] [--syn_b/--syn_c/--syn_d/--syn_e/--syn_p/--syn_s/--syn_samp]

Stereo mixer

mixfiles.py mixes two mono audio files to create a stereo file, e.g.: python3 mixfiles.py right.wav left.wav both.wav

Please note that mixfiles.py inputs and outputs 44.1 kHz WAV files, so do not use this with Pysynth “samp” output (which is 48 kHz) or you will get wrong results.


Interactive command line environment

This feature, contributed by Pranav Ravichandran, is used by running menv.py. It is really self-explaining, you enter your desired notes and any optional parameters like bpm on the command line and after you hit return PySynth synthesizes the sound and plays it back via the speakers. Depending on the speed of your computer and the length of the sound, there might be a slight pause between your input and sound playback.

PyAudio is recommended for playback functionality, but Pyglet, tkSnack, or a command line audio player of your choice are also supported.

Nokia ringtone synthesizer

Pēteris Caune has implemented nokiacomposer2wav.py, which as the name suggests takes a Nokia ringtone and synthesizes it using pysynth_beeper.py. nokiacomposer2wav.py also produces some test files when invoked directly.


Usage

The script can be used as a module by other Python programs or the interactive Python shell:

% python3
>>> import pysynth
>>> test = ( ('c', 4), ('e', 4), ('g', 4), ('c5', 1) )
>>> pysynth.make_wav(test, fn = "test.wav")
Writing to file test.wav
[1/4]

>>> 

…which will give you this timeless masterpiece. That’s the C major chord over the middle C followed by the high C. Three quarters, followed by a whole note (which PySynth assumes to equal 4 quarters).

First comes the note name (a to g), then optionally a '#' or 'b' for sharp or flat, then optionally the octave (defaults to 4). An asterisk at the end means to play the note a little louder.

The note duration comes next, with dotted notes represented by negative numbers (e.g. -2 is a dotted half note). 'r' is a rest. So e.g. “The Blue Danube” starts with:

song = (
                       ('c', 4),
  ('c*', 4), ('e', 4), ('g', 4),
  ('g*', 2), ('g5', 4),
  ('g5*', 4), ('r', 4), ('e5', 4),
  ('e5*', 4) 
)

>>> from pysynth_b import *
*** EXPERIMENTAL PIANO VERSION WITH NOTE CACHING ***
>>> make_wav(song, fn = "danube.wav", leg_stac = .7, bpm = 180)Beats per minute is
                                                                          really quarters
                                                                          per minute here.
[1/10]
[5/10]
[9/10]
Writing to file danube.wav

>>> 

For more convenient note entry, you can e.g. use the ABC notation importer:

This is an example from the ABC documentation:

X: 1
T: Balance the Straw
R: jig
N: This tune goes with one of the best-known Morris dances. It is also a good jig
N: for other dances, usually in AABB form. The B phrase bears a strong resemblance
N: to a certain Christmas carol, and at Morris dances you will hear words like:
N: __ Hark! the herald angels sing, __
N: __ Glory to the Morris Ring. __
N: Sometimes assorted other things are praised by the angels.
N:
M: 6/8
L: 1/8
K: G
D \
|: "G"G2B B>AB | "C"c2A A>ce | "D7"d>ed cAc | "G"G2B B2D \
|  "G"G2B B>AB | "C"c2A A>ce | "D7"d>ed cEF | "G"G4 z2 :|
B/c/ \
|: "G"dz d dz G | "(D7)"c2B "D7"B2A |  "G"dz d dz G | "D7"B2A A2D \
|  "G"G2B B>AB | "C"c2A A>ce | "D7"d>ed cEF | "G"G4 z2 :|

Creating the audio with:

python3 read_abc.py straw.abc

gives you this file.


License

This software is provided under the GPL.

Contact


Sample program output

% time python3 pysynth.py
Piano key frequencies (for equal temperament):
Key number      Scientific name Frequency (Hz)
         1                   A0          27.50
         2                  A#0          29.14
         3                   B0          30.87
         4                   C1          32.70
         5                  C#1          34.65
         6                   D1          36.71
         7                  D#1          38.89
         8                   E1          41.20
         9                   F1          43.65
        10                  F#1          46.25
        11                   G1          49.00
        12                  G#1          51.91
        13                   A1          55.00
        14                  A#1          58.27
        15                   B1          61.74
        16                   C2          65.41
        17                  C#2          69.30
        18                   D2          73.42
        19                  D#2          77.78
        20                   E2          82.41
        21                   F2          87.31
        22                  F#2          92.50
        23                   G2          98.00
        24                  G#2         103.83
        25                   A2         110.00
        26                  A#2         116.54
        27                   B2         123.47
        28                   C3         130.81
        29                  C#3         138.59
        30                   D3         146.83
        31                  D#3         155.56
        32                   E3         164.81
        33                   F3         174.61
        34                  F#3         185.00
        35                   G3         196.00
        36                  G#3         207.65
        37                   A3         220.00
        38                  A#3         233.08
        39                   B3         246.94
        40                   C4         261.63
        41                  C#4         277.18
        42                   D4         293.66
        43                  D#4         311.13
        44                   E4         329.63
        45                   F4         349.23
        46                  F#4         369.99
        47                   G4         392.00
        48                  G#4         415.30
        49                   A4         440.00
        50                  A#4         466.16
        51                   B4         493.88
        52                   C5         523.25
        53                  C#5         554.37
        54                   D5         587.33
        55                  D#5         622.25
        56                   E5         659.26
        57                   F5         698.46
        58                  F#5         739.99
        59                   G5         783.99
        60                  G#5         830.61
        61                   A5         880.00
        62                  A#5         932.33
        63                   B5         987.77
        64                   C6        1046.50
        65                  C#6        1108.73
        66                   D6        1174.66
        67                  D#6        1244.51
        68                   E6        1318.51
        69                   F6        1396.91
        70                  F#6        1479.98
        71                   G6        1567.98
        72                  G#6        1661.22
        73                   A6        1760.00
        74                  A#6        1864.66
        75                   B6        1975.53
        76                   C7        2093.00
        77                  C#7        2217.46
        78                   D7        2349.32
        79                  D#7        2489.02
        80                   E7        2637.02
        81                   F7        2793.83
        82                  F#7        2959.96
        83                   G7        3135.96
        84                  G#7        3322.44
        85                   A7        3520.00
        86                  A#7        3729.31
        87                   B7        3951.07
        88                   C8        4186.01

Creating Demo Songs... (this might take about a minute)

Writing to file pysynth_scale.wav
[1/26]
[5/26]
[9/26]
[13/26]
[17/26]
[21/26]
[25/26]

Writing to file pysynth_anthem.wav
[1/25]
[5/25]
[9/25]
[13/25]
[17/25]
[21/25]
[25/25]

Writing to file pysynth_chopin.wav
[1/29]
[5/29]
[9/29]
[13/29]
[17/29]
[21/29]
[25/29]
[29/29]

Writing to file pysynth_bach_rh.wav
[1/52]
[5/52]
[9/52]
[13/52]
[17/52]
[21/52]
[25/52]
[29/52]
[33/52]
[37/52]
[41/52]
[45/52]
[49/52]
[1/52]
[5/52]
[9/52]
[13/52]
[17/52]
[21/52]
[25/52]
[29/52]
[33/52]
[37/52]
[41/52]
[45/52]
[49/52]

Writing to file pysynth_bach_lh.wav
[1/33]
[5/33]
[9/33]
[13/33]
[17/33]
[21/33]
[25/33]
[29/33]
[33/33]
[1/33]
[5/33]
[9/33]
[13/33]
[17/33]
[21/33]
[25/33]
[29/33]
[33/33]

Mixing files, total length 29.54 s...
0 s
5 s
10 s
15 s
20 s
25 s
63.615u 0.498s 1:06.09 96.9%    0+0k 0+45io 0pf+0w