I programmed a little synthesizer in C++. It listens for MIDI instructions from an instrument, generates a waveform following the instructions, and then sends the waveform to the speakers. It uses the RtMidi and RtAudio libraries to make this work.
It sounds like this:
The synth can generate four types of waveforms (sine, triangle, square, and saw) using wavetable synthesis. In the audio example, you can hear the difference in the quality of sound (timbre) between these waveforms.
The synth works but there are some limitations:
The synth is monophonic: only a single note can be played at once.
There are some clicks and pops in the sound. I think this is either due to performance problems where the program cannot keep the audio buffer filled up for the speakers to read from; or because the sound envelope is designed poorly and the amplitude of the waveform changes too abruptly when a note starts or stops.
This was pretty tough for me to build, but I learned a lot about sound synthesis and MIDI along the way! I think I will try to write more audio software in the future.
I got a lot of help on this from people online. And I was able to borrow a lot of ideas from the roto project, which emulates a Hammond B3 organ. This talk by the creator Peter Teichman is really interesting and fun.