Do You Want to Build a Synthesizer or Be a Synthesizer?

Kraftwerk built theirs from scratch in a Düsseldorf studio and invented the future. Moroder ran his through a Moog and Giorgio'd his way into a billion disco records. The kids making beats on SP-404s in the Bronx rewired what rhythm meant. MGMT made a record that sounds like all of them having a breakdown together. None of them waited for permission. You have a laptop, a browser, and a Python runtime. You have fewer excuses than any of them.

You don't need to know how to solder. You don't need a Eurorack case, a Moog Sub37, a vintage Roland SH-101 in powder blue, or a room full of patch cables that cost more than a semester of community college. You don't need to have grown up in Düsseldorf or spent three years as Giorgio Moroder's assistant or been in a Brooklyn loft in 1983 with a beatbox and a Roland TR-808 that everyone thought sounded like a broken drum set.

What you need is curiosity about sound and the willingness to feel like an idiot for about two hours while you figure out why it makes noise at all.

Everything else follows from that.

A synthesizer is a machine for making sound from electricity. That's it. The complexity people associate with synthesizers — the patch cables, the knobs, the modular systems that cost more than a car — is all in service of that one idea: take electrical signals and shape them until they make the sound you want.

Sound is vibration. Vibration is waves. Waves have three properties that matter: frequency, which you hear as pitch; amplitude, which you hear as volume; and shape, which you hear as timbre — the difference between a piano and a violin playing the same note. A synthesizer generates waves and gives you tools to manipulate those three properties. That's the whole thing. Kraftwerk understood this. Moroder understood this. The engineers at Moog understood this. The kid in 1982 who figured out that an 808's bass drum could be tuned to a pitch and used as a bass line understood this, and that understanding changed popular music permanently.

You're going to understand it too.

The Building Blocks

Every synthesizer — from a 1970s Moog modular the size of a refrigerator to a softsynth plugin running in your DAW to the thing we're about to build — has the same core architecture. Learn these four pieces and you understand every synthesizer ever made.

The oscillator is the sound source. It generates the raw wave at a given frequency. The shape of that wave determines its character before you've touched anything else. A sine wave is a pure tone — single frequency, no harmonics, clean and slightly boring, what a tuning fork makes. A square wave flips between full-on and full-off, rich in odd harmonics, with that hollow reedy quality that runs through early video game music and most of post-punk. A sawtooth ramps up, drops instantly, ramps again — the most harmonically rich of the basic shapes, full of both odd and even harmonics, which is why it's the wave that makes synthesizers sound like synthesizers. The Kraftwerk leads. The Moroder strings. The MGMT arpeggios on Time to Pretend that sound like 1983 dreamed them and 2007 made them real. A triangle wave sits somewhere between sine and square, softer harmonics, gentler presence.

The filter is where personality lives. You take the harmonically rich oscillator output and cut or boost specific frequency ranges. The most important filter in synthesis history is the low-pass filter, which lets low frequencies through and cuts high ones. Sweep it open and you get that classic synthesizer swell — what the 303 bassline does, what the acid house producers discovered could make people lose their minds at 130 BPM. The filter has a cutoff frequency, which is where it starts cutting, and a resonance control, which emphasizes the frequencies right at the cutoff — at high settings, that's the characteristic synth squeal.

The amplifier controls volume over time. Not much to it on its own — it's the gain stage. What makes it interesting is what controls it.

The envelope is time. It's the shape of a sound from start to finish, described in four parameters: attack, how long it takes to reach full volume after a note triggers; decay, how long it takes to fall from the attack peak to the sustain level; sustain, the level it holds while the note is held; release, how long it takes to fade after the note is released. A piano has a fast attack, fast decay, no sustain, and a medium release. A string section has a slow attack, slow decay, high sustain, and a slow release. Change those four numbers and you change the entire character of a sound. The 808's iconic kick drum is a sine wave with a very fast attack, instant decay, no sustain, no release — plus a pitch envelope that drops fast. That's the whole secret. That's what changed hip hop.

ADSR Visualization:

Volume
  |
  |     /\
  |    /  \
  |   /    \______
  |  /              \
  | /                \
  |/                  \___
  +--A---D---S--------R-----> Time

Let's Build One

Here's where we stop talking about synthesizers and start building one. In Python, in your browser, with no hardware required. The first version will make sound. The second version will make something you might actually want to listen to.

Step 1: The Oscillator in Python

import numpy as np
import sounddevice as sd

# Sample rate: 44100 Hz is CD quality
# This is how many samples per second we generate
SAMPLE_RATE = 44100
DURATION = 2.0  # seconds

def oscillator(frequency, waveform='sine', duration=DURATION, sample_rate=SAMPLE_RATE):
    """
    Generate a basic waveform.
    frequency: pitch in Hz (440 = A4, concert pitch)
    waveform: 'sine', 'square', 'sawtooth', 'triangle'
    """
    t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    
    if waveform == 'sine':
        wave = np.sin(2 * np.pi * frequency * t)
    
    elif waveform == 'square':
        wave = np.sign(np.sin(2 * np.pi * frequency * t))
    
    elif waveform == 'sawtooth':
        # Sawtooth: ramps from -1 to 1 each cycle
        wave = 2 * (t * frequency - np.floor(t * frequency + 0.5))
    
    elif waveform == 'triangle':
        wave = 2 * np.abs(2 * (t * frequency - np.floor(t * frequency + 0.5))) - 1
    
    return wave.astype(np.float32)

# Make some noise
wave = oscillator(440, waveform='sawtooth')
sd.play(wave, SAMPLE_RATE)
sd.wait()

Install the dependencies first:

pip install numpy sounddevice

Run that. You'll hear a raw sawtooth wave at A4 (440 Hz). It sounds harsh and buzzy. That's correct. That's the raw material. Everything else is shaping it.

Step 2: The Envelope

def adsr_envelope(duration, attack, decay, sustain_level, release,
                  sample_rate=SAMPLE_RATE):
    """
    Returns an amplitude envelope array.
    All time values in seconds. sustain_level is 0.0 to 1.0.
    """
    total_samples = int(duration * sample_rate)
    envelope = np.zeros(total_samples)
    
    a_samples = int(attack * sample_rate)
    d_samples = int(decay * sample_rate)
    r_samples = int(release * sample_rate)
    s_samples = total_samples - a_samples - d_samples - r_samples
    s_samples = max(0, s_samples)
    
    # Attack: ramp up
    envelope[:a_samples] = np.linspace(0, 1, a_samples)
    
    # Decay: ramp down to sustain
    envelope[a_samples:a_samples+d_samples] = np.linspace(1, sustain_level, d_samples)
    
    # Sustain: hold
    envelope[a_samples+d_samples:a_samples+d_samples+s_samples] = sustain_level
    
    # Release: ramp down to zero
    envelope[total_samples-r_samples:] = np.linspace(sustain_level, 0, r_samples)
    
    return envelope.astype(np.float32)

# Sawtooth wave shaped by an envelope
wave = oscillator(440, waveform='sawtooth', duration=2.0)
env = adsr_envelope(
    duration=2.0,
    attack=0.01,     # fast attack
    decay=0.1,       # quick decay
    sustain_level=0.6,
    release=0.3      # smooth release
)

shaped = wave * env

sd.play(shaped, SAMPLE_RATE)
sd.wait()

Same frequency. Same waveform. Completely different character. The envelope is doing all of it.

Step 3: The Filter

from scipy import signal

def low_pass_filter(wave, cutoff_hz, resonance=0.7, sample_rate=SAMPLE_RATE):
    """
    Simple low-pass filter.
    cutoff_hz: filter cutoff frequency
    resonance: Q factor (higher = more resonant peak at cutoff)
    """
    # Normalize cutoff to Nyquist frequency
    nyquist = sample_rate / 2
    normalized_cutoff = cutoff_hz / nyquist
    normalized_cutoff = np.clip(normalized_cutoff, 0.001, 0.999)
    
    # Butterworth filter — smooth rolloff, no ripple
    b, a = signal.butter(2, normalized_cutoff, btype='low', analog=False)
    filtered = signal.lfilter(b, a, wave)
    
    return filtered.astype(np.float32)

# Now: oscillator → envelope → filter
wave = oscillator(110, waveform='sawtooth', duration=3.0)  # low A
env = adsr_envelope(3.0, attack=0.05, decay=0.2, sustain_level=0.7, release=0.5)
shaped = wave * env

# Apply filter — try changing cutoff_hz from 200 to 3000 and hear the difference
filtered = low_pass_filter(shaped, cutoff_hz=800)

sd.play(filtered, SAMPLE_RATE)
sd.wait()

Install scipy:

HACK LOVE BETRAY
COMING SOON

HACK LOVE BETRAY

Mobile-first arcade trench run through leverage, trace burn, and betrayal. The City moves first. You keep up or you get swallowed.

VIEW GAME FILE
pip install scipy

Now change cutoff_hz from 200 to 4000 and run it again. That's the filter opening up. That's the sound. That's what synthesizers do.

Step 4: Play a Sequence

def note_to_hz(note_name):
    """Convert note names to frequencies. A4 = 440 Hz."""
    notes = {'C': 0, 'C#': 1, 'D': 2, 'D#': 3, 'E': 4, 'F': 5,
             'F#': 6, 'G': 7, 'G#': 8, 'A': 9, 'A#': 10, 'B': 11}
    
    name = note_name[:-1]
    octave = int(note_name[-1])
    semitones = (octave - 4) * 12 + notes[name] - 9  # relative to A4
    return 440.0 * (2 ** (semitones / 12))

def play_sequence(sequence, bpm=120, waveform='sawtooth'):
    """
    sequence: list of (note, duration_in_beats) tuples
    bpm: tempo
    """
    beat_duration = 60.0 / bpm
    audio_parts = []
    
    for note, beats in sequence:
        dur = beats * beat_duration
        freq = note_to_hz(note)
        
        wave = oscillator(freq, waveform=waveform, duration=dur)
        env = adsr_envelope(dur, attack=0.01, decay=0.05,
                            sustain_level=0.7, release=0.08)
        shaped = wave * env * 0.4  # scale amplitude down
        filtered = low_pass_filter(shaped, cutoff_hz=1200)
        audio_parts.append(filtered)
    
    full_audio = np.concatenate(audio_parts)
    sd.play(full_audio, SAMPLE_RATE)
    sd.wait()

# A simple descending sequence
# Tweak the notes and watch it turn into something
sequence = [
    ('A3', 0.5), ('G3', 0.5), ('F3', 0.5), ('E3', 0.5),
    ('D3', 0.5), ('C3', 0.5), ('D3', 0.5), ('E3', 1.0),
]

play_sequence(sequence, bpm=120, waveform='sawtooth')

You now have a sequenced synthesizer running in Python. Moroder was doing this with a Moog and a multitrack tape recorder. You're doing it with a laptop and twenty-dollar libraries. The underlying physics is identical.

From here the directions are essentially unlimited. Two oscillators detuned slightly from each other create a beating interference pattern that sounds massive — that's the supersaw, that's why EDM leads sound like that. A low frequency oscillator running below the range of human hearing pointed at the filter cutoff opens and closes the filter rhythmically, which is the wah sound; pointed at pitch, it's vibrato; pointed at amplitude, it's tremolo. Add reverb and you put the synth in a room. Add delay and the room has an echo. If hardware is calling you, the Eurorack modular format is the endgame rabbit hole — individual modules connected with patch cables, every connection a decision, as deep as you want to go.

You should also listen to the people who built the vocabulary. Kraftwerk's Autobahn — twenty-two minutes, built from custom synthesizers and vocoders in a studio in Düsseldorf in 1974, and every electronic music genre that followed traces a line back to it. Moroder and Donna Summer's I Feel Love — the first fully synthesized number one hit, sequenced on a Moog modular, and Brian Eno heard it and told a journalist it had changed the face of pop music. He wasn't wrong. Afrika Bambaataa's Planet Rock — took the Kraftwerk drum patterns, ran them through a TR-808, added a vocoder, and invented electro. The 808 kick on that record is a sine wave with a pitch envelope. That one insight invented a sonic universe. And MGMT's Oracular Spectacular — the 21st century answer to all of the above, synth-forward and maximalist and completely its own thing. If that's your entry point into synthesizers, there are worse doors.

Into the DAW

Your Python synth makes sound. What it doesn't do is live inside your DAW, respond to MIDI notes in real time, get automated, get recorded to a track, or show up in Ableton's instrument list. The difference between a Python script and a VST plugin is the container — the wrapper that tells your DAW "this is an instrument, here's how to talk to it."

That wrapper is traditionally written in C++ using a framework called JUCE. For years, this was the wall. You could understand synthesis cold and still spend three months learning C++ before your first JUCE note came out. The physics was accessible. The engineering ceremony was not.

AI closed that gap.

The DSP logic you just wrote — the oscillator functions, the ADSR, the filter — translates almost directly from Python to JUCE C++. Your np.sin(2*pi*f*t) becomes juce::dsp::Oscillator. Your signal.butter() becomes juce::dsp::LadderFilter. Your sample loop becomes processBlock(). The concepts are identical. The syntax changes. AI handles the syntax.

The practical workflow: paste your Python synth into Claude or Cursor and ask it to translate the DSP logic into a JUCE AudioProcessor. You'll get working C++ back — not perfect, you'll tune it, but the scaffold is there in minutes instead of weeks. The boilerplate around it (the plugin class, parameter handling, MIDI input, audio output routing, plugin metadata) is exactly the kind of structural code AI writes well. The musical logic — your oscillator shapes, your envelope curve, your filter character — is yours. AI handles the ceremony.

Three free tools to install before you build: CMake (the build system), Xcode on Mac or Visual Studio on Windows (the C++ compiler, both free), and JUCE itself (free for personal use, commercial license for commercial plugins). Once those are in place, the build is four commands:

npm install && npm run build   # build the UI layer if you have one
mkdir build && cd build
cmake ..
cmake --build . --config Release

The result lands at build/YourPlugin_artefacts/Release/VST3/YourPlugin.vst3. Drop that file into your DAW's plugin folder. Scan for new plugins. Your oscillator is now an instrument.

This is not a distant or theoretical thing. It is being done right now, largely in silence, by people who understand synthesis but are not C++ engineers. AI-assisted audio plugin development is one of the more genuinely overlooked consequences of the current moment in AI tooling. The musicians who figure this out first are going to have custom instruments that fit their practice exactly — not the Moog they couldn't afford, not the plugin that almost does what they want — their instrument, built to spec, running natively in the DAW they already use.

Kraftwerk built the synthesizers they needed because the ones that existed weren't right. The tools to do that are now available to anyone who understands the physics above and is willing to paste code into a chat window.

The MIKEY MK-78 is my contribution to the vibration. Eight-voice polyphonic, built on JUCE 8, runs as a web app, a standalone desktop instrument, and a native VST3/AU plugin. The README says it plainly: CRAFTED BY ROBOTS. That's not a disclaimer. That's the point. The source is on GitHub. Get in the signal.


GhostInThePrompt.com // Kraftwerk didn't wait for permission. You have fewer excuses than any of them.