Building a MIDI Synthesizer in Julia: Recreating Plantasia
Mother Earth's Plantasia is a cult classic electronic album entirely composed using Moog synthesizers. The album was released in 1976 and intended to be listened to by plants. Some of my favorite tracks are "Plantasia," "Symphony for a Spider Plant," and "Swingin’ Spathiphyllums." A college roommate introduced me to Plantasia, and during a camping trip, I visited the Moog Museum in Asheville, NC. This inspired me to experiment with synthesizers to recreate the titular track.
Listen to Plantasia
Here's some output from the synthesizer:
Technical Implementation
MIDI Processing
The synthesizer takes MIDI files as input, which contain:
- Note events (pitch, velocity, timing, noteOn, noteOff)
- I used MIDI.jl to parse MIDI files and leveraged its convenient getNotes function to extract all notes from each track.
- Metadata (tempo changes, pitch bends, etc. - currently ignored in this version)
Each note contains:
pitch
: Starting from C-1 = 0, incrementing by semitonevelocity
: How loud the note is (0-127)position
: Absolute time position in ticksduration
: Length in ticks
Synthesis Components
-
Waveform Generation
Basic waveforms implemented using Fourier series:
- Sine wave with vibrato
- Square wave
- Triangle wave
- Saw wave
The sine wave supports a vibrato effect, while the other waveforms allow customization of the number of harmonics summed to shape the sound
-
ADSR Envelope
- An envelope shapes the dynamics of a sound over time, defining how it starts, sustains, and fades.
- Attack: Initial rise time
- Decay: Fall to sustain level
- Sustain: Maintained amplitude level
- Release: Fade out to the end of the note
- Typically, the Release stage begins after a noteOff event. However, in this implementation, the sound stops immediately upon receiving noteOff.
Prevents clicking and adds natural dynamics.
-
Instrument Presets
Each instrument combines:
- A waveform function
- ADSR envelope parameters
Can create varied timbres from basic building blocks.
Core Functions
# Converts a MIDI track to audio samples
synthesize_track
# Processes full MIDI file with multiple tracks
synthesize_midi
# Generates ADSR envelope
generate_adsr_envelope
Audio Output
Renders to WAV files at 44.1kHz
Current Limitations
- Metadata tracks (like pitch bend) are not processed
- Performance optimization is needed for real-time playback and for all-around faster synthesis. It takes around 10 seconds to generate audio for longer files like plantasia and Lacrimosa, and less than two seconds for Avril 14th.
- Limited set of basic waveforms and synthesis methods
Future Improvements
Topics that future posts could explore:
- Performance optimizations
- Effects such as non-linear distortion and delay
- Additional synthesis techniques
- Extended MIDI feature support
- Drum kit synthesis
- Sampling
The code is a work in progress, but it successfully renders simple MIDI files into listenable audio.
Bonus Track
Avril 14th