How to build a digital music synthesizer
By Tina Belmont- SoftEgg LLC
How to build a digital music synthesizer
(in two minutes)
Music is sound that communicates emotion
Duh.
Sounds are vibrations in the air
Air can be vibrated by a speaker
Speaker can be attached to a pin of a microcontroller
You might want an amplifier in between for best results.
Use a D/A pin or PWM.
Parameters of sound
Frequency (aka Pitch)
Parameters of sound
Frequency (aka Pitch)
Parameters of Sound
Amplitude (aka volume)
Parameters of Sound
Harmonic content (generally, the waveform)
Output sound from microcontroller
Store waveform in a table of numbers
Output sound from a microcontroller
Store waveform in a table of numbers.
You could store a whole recording of an instrument.
Output sound from a microcontroller
Store waveform in a table of numbers.
You could store a whole recording of an instrument.
This is called digital sampling.
Output sound from a microcontroller
Store waveform in a table of numbers.
You could store a whole recording of an instrument.
This is called digital sampling.
We’re not going to do that because we are making a synthesizer.
Output sound from a microcontroller
Store waveform in a table of numbers.
You could store a whole recording of an instrument.
This is called digital sampling.
We’re not going to do that because we are making a synthesizer.
Microcontrollers don’t have that much memory anyway.�
Output sound from a microcontroller
We just want one period of a simple waveform.
We can loop it.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�
Different pitches from one waveform
Skip or duplicate table entries for different speeds / pitches.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
It’s a slightly flat F3… (which is 174.61Hz)
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
It’s a slightly flat F3… how do we get actual notes?
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
D/A output is always the same speed (sample rate).�Skip or duplicate table entries for different speeds.
Different pitches from one waveform
Aliasing may be an issue!
Different pitches from one waveform
Aliasing may be an issue! Nyquist frequency is a thing!
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
C0 is 16.35Hz.
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
C0 is 16.35Hz.
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
C0 is 16.35Hz.
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
C0 is 16.35Hz.
Make it a power of two for reasons. 2048 or 4096 plz.
Different pitches from one waveform
Avoid low frequency grit by making sample table large enough for the lowest note.
C0 is 16.35Hz.
Make it a power of two for reasons. 2048 or 4096 plz.
Or live with the grit… maybe you like it!
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
So the frequency of each note increases as .
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
So the frequency of each note increases as .
Or
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
So the frequency of each note increases as .
Or
Traditional tuning has A4 at 440 Hz.
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
So the frequency of each note increases as .
Or
Traditional tuning has A4 at 440 Hz.
Just make or copy a table and stick it in your code, OK?
What are note frequencies?
Octave is 12 notes (“half-steps” because music is stupid.)
Each octave doubles in pitch.
So the frequency of each note increases as .
Or
Traditional tuning has A4 at 440 Hz.
Just make or copy a table and stick it in your code, OK?
If you want fine tuning:
Help!
Help!
My microcontroller can’t
Help!
My microcontroller can’t FLOATING POINT!
Bro!
Bro!
Do you even
Bro!
Do you even
FIXED POINT MATH?
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Multiply by a value to bring fractional part into integer space.
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Multiply by a value to bring fractional part into integer space.
Use a power of 2, so that you can use shift operators << >>.
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Multiply by a value to bring fractional part into integer space.
Use a power of 2, so that you can use shift operators << >>.
Example:
1<<8 = 256 or 0x100
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Multiply by a value to bring fractional part into integer space.
Use a power of 2, so that you can use shift operators << >>.
Example:
1<<8 = 256 or 0x100 (0x means hexadecimal, duh!)
Bro! Do you even FIXED POINT MATH?
It’s just bloody fractions!
Multiply by a value to bring fractional part into integer space.
Use a power of 2, so that you can use shift operators << >>.
Example:
1<<8 = 256 or 0x100 (0x means hexadecimal, duh!)
So to to get 0.5, divide 256 by 2 (>>=1) = 128 (0x80)
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
If your values only go 0 to 1, then you can use the entire precision; all the bits!
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
If your values only go 0 to 1, then you can use the entire precision; all the bits!
If you need negative numbers, leave a bit at the top.
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
If your values only go 0 to 1, then you can use the entire precision; all the bits!
If you need negative numbers, leave a bit at the top.
Don’t forget to leave overflow precision to do math on stuff when multiplying.
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
If your values only go 0 to 1, then you can use the entire precision; all the bits!
If you need negative numbers, leave a bit at the top.
Don’t forget to leave overflow precision to do math on stuff when multiplying. Sometimes do math in a higher precision space than you store if necessary.
Bro! Do you even FIXED POINT MATH?
Pick a precision that works for the problem that you are trying to solve, and is best for your processor.
If your values only go 0 to 1, then you can use the entire precision; all the bits!
If you need negative numbers, leave a bit at the top.
Don’t forget to leave overflow precision to do math on stuff when multiplying. Sometimes do math in a higher precision space than you store if necessary.
Don’t forget to shift right after a multiplication!
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0.
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0. So volume is also level 0-255.
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0. So volume is also level 0-255.
Give ourselves 16 bits for math. Easy in C (uint16_t).
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0. So volume is also level 0-255.
Give ourselves 16 bits for math. Easy in C (uint16_t).
Multiple the two values together.
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0. So volume is also level 0-255.
Give ourselves 16 bits for math. Easy in C (uint16_t).
Multiple the two values together.
Shift right 8 bits to cancel out the 8 bits we added with the volume multiply.
Fixed point math example: Volume
Let’s say the sample is 8 bits, 0 to 255 (0x00 to 0xFF).
We want to allow fade to 0. So volume is also level 0-255.
Give ourselves 16 bits for math. Easy in C (uint16_t).
Multiple the two values together.
Shift right 8 bits to cancel out the 8 bits we added with the volume multiply.
Result is the new output sample.
This sounds boring.
This sounds boring.
Let’s make it interesting.
Use two or more oscillators
Options:
Use two or more oscillators
Options:
Use two or more oscillators
Options:
Use two or more oscillators
Options:
Use envelopes
Envelope is change in value of a parameter over time.
Use envelopes
Envelope is change in value of a parameter over time.
Apply to volume, pitch, filter, any parameter… go wild!
Use envelopes
Envelope is change in value of a parameter over time.
Apply to volume, pitch, filter, any parameter… go wild!
It’s a state machine, you are programmers, figure it out!
You keep mentioning “Filters”...
You keep mentioning “Filters”...
WTF is a “Filter”?
WTF is a Filter?
Reduces harmonic content of a signal.
WTF is a Filter?
Reduces harmonic content of a signal.
Sounds cool when you sweep it with an envelope or LFO!
WTF is a Filter?
Reduces harmonic content of a signal.
Sounds cool when you sweep it with an envelope or LFO!
Low-pass is most common, but high-pass and band-pass are also used.
WTF is a Filter?
Reduces harmonic content of a signal.
Sounds cool when you sweep it with an envelope or LFO!
Low-pass is most common, but high-pass and band-pass are also used.
Go Google some algorithms!
feedbackAmount = resonance + resonance/(1.0 - cutoff);
buf0 += cutoff * (inputValue - buf0 + feedbackAmount * (buf0 - buf1));
buf2 += cutoff * (buf1 - buf2);
buf3 += cutoff * (buf2 - buf3);
switch (mode) {
case FILTER_MODE_LOWPASS:
return buf3;
case FILTER_MODE_HIGHPASS:
return inputValue - buf3;
case FILTER_MODE_BANDPASS:
return buf0 - buf3;
default:
return 0.0;
Play notes via MIDI!
MIDI is dirt simple.
Play notes via MIDI!
MIDI is dirt simple.
Serial at 31250 bits per second with start and stop bits.
Play notes via MIDI!
MIDI is dirt simple.
Serial at 31250 bits per second with start and stop bits.
If high bit is set, is a command. Otherwise last command stands.
Play notes via MIDI!
MIDI is dirt simple.
Serial at 31250 bits per second with start and stop bits.
If high bit is set, is a command. Otherwise last command stands.
High nybble is command (0x9X = note on, 0x80 = note off)
Low nybble is MIDI channel.
Play notes via MIDI!
MIDI is dirt simple.
Serial at 31250 bits per second with start and stop bits.
If high bit is set, is a command. Otherwise last command stands.
High nybble is command (0x9X = note on, 0x80 = note off)
Low nybble is MIDI channel.
Data for Note On / Off is two bytes: key # and velocity.
Play notes via MIDI!
Just use the default Arduino library from �Forty Seven Effects at https://github.com/FortySevenEffects/arduino_midi_library .
Install via Arduino Library Manager.
Play notes via MIDI!
Just use the default Arduino library from �Forty Seven Effects at https://github.com/FortySevenEffects/arduino_midi_library .
Install via Arduino Library Manager.
PJRC Teensy gives you MIDI over USB for free via bootloader options!
Play notes via MIDI!
Just use the default Arduino library from �Forty Seven Effects at https://github.com/FortySevenEffects/arduino_midi_library .
Install via Arduino Library Manager.
PJRC Teensy gives you MIDI over USB for free via bootloader options!
If your keyboard has knobs and / or sliders you can adjust parameters via CC messages; no UI necessary!
How to build a digital music synthesizer
The End