Code a simple synthesiser – Part 1

Learn how to write a simple polyphonic synthesiser (and the theory behind it) using Python and Cython

We are going to take you through the basics of wavetable synthesis theory and use that knowledge to create a real-time synthesiser in Python. At the moment, it is controlled by the computer keyboard, but it could easily be adapted to accept a MIDI keyboard as input.

The Python implementation of such a synthesiser turns out to be too slow for polyphonic sound (ie playing multiple notes at the same time) so we’ll use Cython, which compiles Python to C so that you can then compile it to native machine code to improve the performance. The end result is polyphony of three notes, so this is not intended for use as a serious synthesiser. Instead, this tutorial will enable you to become familiar with synthesis concepts in a comfortable language: Python.

Once you’re finished, try taking this project further by customising the mapping to better fit your keyboard layout, or tweaking the code to read input from a MIDI keyboard.

1. Install packages

Using the latest Raspbian image, install the required packages with the following commands:

  sudo apt-get update

  sudo apt-get upgrade

  sudo apt-get install python-pip python2.7-dev portaudio19-dev

  sudo pip install cython pyaudio

The final step compiles Cython and PyAudio from source, so you might want to go and do something else while it works its magic.

2. Disable built-in sound card

We had issues getting the Raspberry Pi’s built-in sound card to work reliably while developing the synthesis code. For that reason, we are using a USB sound card and will disable the built-in card so that the default card is the USB one:

  sudo rm /etc/modprobe.d/alsa*

  sudo editor /etc/modules

Change ‘snd-bcm2835’ to ‘#snd-bcm2835’ and save, then:

  sudo reboot

3. Test sound card

Now we can test the USB sound card. Type alsamixer and then ensure that the volume is set to a comfortable level. If you’re plugging speakers in, you’ll probably want it set to 100%. Then type speaker-test, which will generate some pink noise on the speakers. Press Ctrl+C to exit once you are happy that it’s working.

An angled, isolated, studio lit shot of an electric keyboard.
An angled, isolated, studio lit shot of an electric keyboard.

4. Start project

Start by creating a directory for the project. Then download one cycle of a square wave that we will use as a wavetable, like so:

  mkdir synth

  cd synth


5. Create compilation script

We need a script that will profile our Python code (resulting in synth.html). Generate a Cython code for it and finally compile the Cython code to a binary with GCC:



  cython -a synth.pyx

  cython –embed synth.pyx

  gcc -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -O3 -I /usr/include/python2.7 -o synth.bin synth.c -lpython2.7 -lpthread

(Notice the options that tell the compiler to use the floating point unit.) Make it executable with:

  chmod +x

6. Start to code

Our code file is going to be called synth.pyx. This extension tells Cython that it is not plain Python code (and as such, can’t be ran in a normal Python interpreter). Create the file with your favourite editor and add the imports.

7. MIDI Table

To synthesise the standard note of a piano, we need a table of MIDI values. MIDI notes range from 0-127. MIDI note 60 is middle C on a piano. The MIDI Table class has a ‘get note’ function that returns the frequency of a note when you give it a MIDI note number.


Full Code for step 7

class MIDITable:

    # Generation code from


    def __init__(self):

        self.notes = []


    def fill_notes(self):

        # Frequency of MIDI note 0 in Hz

        frequency = 8.175799


        # Ratio: 2 to the power 1/12

        ratio = 1.0594631

        for i in range(0, 128):


            frequency = frequency * ratio

    def get_note(self, n):

        return self.notes[n]

Continue this project with part two, which will be available from the 6th of February on