In this post we will explain how to generate high quality sound with Arduino using wavetable synthesis, with bagpipes in mind, of course!!!
The code used here is based in the eChanter, a DIY electronic bagpipes project built around Arduino. Thanks eChanter for the inspiration. We added some cool features in order to let people create custom fingering tables and sound samples.
Wavetable Synthesis in Arduino
The easiest way for sound generation in Arduino is using PCM and PWM. This means that we have the sound samples stored in the Arduino memory (PCM, Wavetable Synthesis) and we periodically loop this stored samples using PMW.
PCM streams have two basic properties that determine their fidelity to the original analog signal: the sampling rate, which is the number of times per second that samples are taken; and the bit depth, which determines the number of possible digital values that each sample can take (Wikipedia).
Due to the limitations of the Arduino PWM we can use only 8 bits bit depth, but regarding sample rate we are able to use up to 44100 Hz, as long as we don’t need to do a lot of processing in the Arduino loop().
How does it works? A periodic function called ISR interrupts the Arduino loop() every 1/44100 seconds, reads the next sample value stored in the FLASH memory, and updates the PWM register in order to generate an analog signal in the PMW pin. The PWM output is not a true anlog signal but a pulse train, so the generated sound will have some high frecuency noise.
So, we need to store in the Aduino memory the sound samples for every note we wanto to play, and we have basically two ways:
- Storing a true sound sample loop. We need to record a good sample of every instrument note and edit this sound sample in order to make it a loop (learn more).
- Storing a digitally generated sound sample based on additive synthesis. We can analyze a true sound, extract the partials and then use this information for generating the loop.
Our choice is the number 2. We used a small python script that generates the loops ready for storing in the Arduino memory based on additive synthesis.
The Arduino sketch provided has sound samples for Gaita Galega (Galician Bagpipe) and Great Highland Bagpipe. If you would like to generate a different instrument, and you can’t manage to analyze the sound partials, please drop us a line (and attach the sound samples).
Not every bagpipes have the same fingerings, so we need a way to relate fingers positions and notes. We wrote a python script in order to let people create new openpipe fingerings for any instrument. We’ve currently defined Gaita Galega (Galician Bagpipe) and Great Highland Bagpipe fingerings.
Here you can see the way we define a fingering.
# GREAT HIGHLAND BAGPIPE #http://www.bagpipejourney.com/articles/finger_positions.shtml great_highland_bagpipe=( ("GREAT HIGHLAND BAGPIPE"), #FINGERING NAME (67), #BASE MIDI NOTE (THE LOWEST IN THE TABLE) G4 (69), #TONIC MIDI NOTE A4 (57), #DRONE MIDI NOTE #FINGERINGS (SEMITONES FROM BASE NOTE, (FINGERINGS,)) (0,("-C CCC CCCC",)), # LOW G (G4) (2,("-C CCC CCCO",)), # LOW A (A4) (4,("-C CCC CCOO",)), # B (B4) (5,("-C CCC COOC", "-C CCC CO--")), # C (C5) (7,("-C CCC OOOC", "-C CCC OO--")), # D (D5) (9,("-C CCO CCCO", "-C CCO ----")), # E (E5) (10,("-C COO CCCO", "-C COO ----")), # F (F5) (12,("-C OOO CCCO", "-C OOO ----")), # HIGH G (G5) (14,("-O OOO CCCO", "-O OOO ----")), # HIGH A (A5) )
Step by Step
If you want to DIY you will need:
Connect OpenPipe Breakout to Arduino GND, 5V and I2C pins.
- Gray wire to GND pin
- White wire to 5V pin
- Green wire to A4 pin
- Yellow wire to A5 pin
- Download the openpipe code
- Go to the openpipe_breakout_echanter folder
- Open the .ino sketch with Arduino IDE
- Upload it to the Arduino UNO
You must place your right thumb over the bottom electrode on the back of the pipe to play.
Can you hear the drone? Yes! We also have a drone!!!
With an RC low-pass filter and amplified speakers the sound is much better.