A fully interactive web-based synthesizer that generates all possible synth waveforms using the Web Audio API. Zero frameworks, zero dependencies - pure HTML, CSS, and JavaScript.
🔗 Repository: github.com/cesp99/SynthLab
# Clone the repository
git clone https://github.com/cesp99/SynthLab.git
cd SynthLab
# Open in any modern browser
open index.html
# or
python3 -m http.server 8080 # then visit http://localhost:8080- Click the power button (top-right) to enable audio
- Use your computer keyboard or click the on-screen piano to play
- Switch between 10 waveform types using the selector grid
- Shape the sound with filters, envelope, and delay
This is a fully static site — no build step required.
- Push the repository to GitHub (default branch
mainormaster). - Go to Settings → Pages.
- Under Source, select Deploy from a branch and pick
main/masterand/ (root). - Save. Your app will be live at
https://<user>.github.io/<repo>/within a minute.
The repo includes a .nojekyll file at the root so GitHub Pages serves the site with Jekyll bypassed — this matters because files starting with _ (none currently, but future-proof) would otherwise be hidden. All asset paths (styles.css, app.js) are relative, so the app works from any subpath with no configuration.
Any static host works: Netlify (Drop the folder), Vercel, Cloudflare Pages, or python3 -m http.server for local.
SynthLab is fully usable on phones, including small devices like the iPhone SE (320px wide):
- The layout stacks vertically on screens narrower than 900px and lets the page scroll naturally.
- The piano keyboard scrolls horizontally and supports multi-touch — drag your finger across the keys for glissando.
- The visualizers, envelopes, and waveform grid all adapt to the available width.
- Tap the power button (top right) once to enable audio; iOS will then keep the AudioContext running.
For best results, add the site to your home screen on iOS — it will launch fullscreen like a native app.
SynthLab implements 10 distinct waveform synthesis methods:
| Wave | Sound | Harmonics | Use Case |
|---|---|---|---|
| Sine | Pure, clean tone | None (fundamental only) | Sub bass, pure tones, FM carrier |
| Square | Hollow, retro | Odd only (1, 3, 5, 7...) | Chiptune, leads, organ |
| Sawtooth | Bright, buzzy | All (1, 2, 3, 4...) | Leads, pads, brass |
| Triangle | Soft, flutey | Odd only, steep rolloff | Flute, soft pads, bass |
| Wave | Method | Parameters | Character |
|---|---|---|---|
| Pulse | Variable duty cycle via Fourier series | Duty Cycle (1-99%) | Nasal, reed-like, thin at narrow widths |
| White Noise | Random sample buffer | Bandpass frequency | Percussion, textures, wind, risers |
| Wave | Method | Parameters | Character |
|---|---|---|---|
| FM | Carrier modulated by modulator frequency | Ratio (0.5-16:1), Depth (0-1000 Hz) | Metallic, bell-like, electric piano |
| AM | Carrier amplitude modulated at audio rates | Rate (0.5-20x), Depth (0-100%) | Ring modulator, clangorous, inharmonic |
| Wave | Method | Parameters | Character |
|---|---|---|---|
| Comb | Feedback delay line with noise excitation | Delay (1-100 ms), Feedback (0-95%) | Metallic resonances, string simulation |
| Wavetable | Additive synthesis (8 harmonics) | H1-H8 amplitude (0-100%) | Custom timbres from simple to complex |
| Control | Range | Default | Description |
|---|---|---|---|
| Frequency | 20 - 2000 Hz | 440 Hz | Base pitch of the oscillator |
| Detune | -100 to +100 ct | 0 ct | Fine pitch adjustment in cents |
| Volume | 0 - 100% | 50% | Master output level |
| Control | Range | Default | Description |
|---|---|---|---|
| Type | LP / HP / BP / Notch | Low Pass | Filter mode |
| Cutoff | 20 - 20,000 Hz | 5.0 kHz | Frequency cutoff point |
| Resonance | 0.1 - 30 | 1.0 | Q factor / emphasis at cutoff |
| Stage | Range | Default | Description |
|---|---|---|---|
| Attack | 1 - 2000 ms | 10 ms | Time to reach peak level |
| Decay | 1 - 2000 ms | 100 ms | Time to fall from peak to sustain |
| Sustain | 0 - 100% | 70% | Level held while note is pressed |
| Release | 1 - 3000 ms | 300 ms | Time to fade to silence after release |
| Control | Range | Default | Description |
|---|---|---|---|
| Time | 0 - 1.0 s | 0.30 s | Delay time |
| Feedback | 0 - 90% | 30% | Amount of signal fed back |
| Mix | 0 - 100% | 0% | Wet/dry balance (0 = dry only) |
Pulse: Duty cycle (1-99%) - controls the width of the pulse wave.
FM: Ratio (0.5-16:1) - frequency relationship between carrier and modulator. Depth (0-1000 Hz) - modulation intensity.
AM: Rate (0.5-20x) - modulator frequency relative to carrier. Depth (0-100%) - modulation amount.
Comb: Delay (1-100 ms) - delay line length. Feedback (0-95%) - resonance amount.
Wavetable: H1-H8 - amplitude of each harmonic overtone (1st through 8th).
The computer keyboard maps to a 2-octave range (C4 to C5):
Black keys: W E T Y U
| | | | |
White keys: A S D F G H J K
| | | | | | | |
Note: C4 D4 E4 F4 G4 A4 B4 C5
MIDI: 60 62 64 65 67 69 71 72
| Key | Note | MIDI | Key | Note | MIDI |
|---|---|---|---|---|---|
| A | C4 | 60 | T | F#4 | 66 |
| W | C#4 | 61 | G | G4 | 67 |
| S | D4 | 62 | Y | G#4 | 68 |
| E | D#4 | 63 | H | A4 | 69 |
| D | E4 | 64 | U | A#4 | 70 |
| F | F4 | 65 | J | B4 | 71 |
| K | C5 | 72 |
┌─────────────────────────────────────┐
│ Signal Chain │
└─────────────────────────────────────┘
Oscillators ──→ Filter ──→ Master Gain ──┬──→ Compressor ──→ Analyser ──→ Output
(per note) (Biquad) (volume) │ (limiter) (visualizer)
│
└──→ Delay ──→ Wet Gain ──→┘
(feedback loop)
- Oscillators: Created per-note, destroyed on release (polyphonic)
- Filter: Shared BiquadFilterNode (LP/HP/BP/Notch)
- Master Gain: Global volume control
- Compressor: Safety limiter (threshold -18 dB, ratio 6:1)
- Delay: Stereo-capable delay with feedback loop
- Analyser: FFT-based for oscilloscope and spectrum display
| Browser | Status |
|---|---|
| Chrome 66+ | Full support |
| Firefox 76+ | Full support |
| Safari 14.1+ | Full support |
| Edge 79+ | Full support |
Requires Web Audio API and Canvas support. No polyfills needed for modern browsers.
synthlab/ # local checkout name (repo on GitHub is `SynthLab`)
├── index.html (353 lines) - UI structure and controls
├── styles.css (523 lines) - Dark theme, responsive layout
├── app.js (753 lines) - Web Audio engine and UI logic
└── README.md - This file
Total: ~1,630 lines of hand-written code. Zero dependencies.
# Any static server works
python3 -m http.server 8080
npx serve .
php -S localhost:8080- No build step - files are served as-is
- IIFE pattern -
app.jswraps everything in an immediately-invoked function - Class-based -
SynthLabclass manages all state and audio nodes - Dynamic piano - keys are generated from
PIANO_KEYSarray, not hardcoded in HTML - Canvas rendering - visualizers use
requestAnimationFrameloop - Memory management - oscillators are stopped and disconnected after release
-
Add a button in
index.htmlinside#wave-selector:<button class="wave-btn" data-wave="yourwave" title="Your Wave"> <svg viewBox="0 0 40 24"><path d="..."/></svg> <span>Name</span> </button>
-
Add a wave-specific section in
#wave-specific-container:<div id="yourwave-section" class="wave-type-specific hidden"> <div class="slider-row">...</div> </div>
-
Add the case in
app.jsinsidenoteOn():case 'yourwave': { // Create oscillators and connect to env node // Push all nodes to data.nodes array break; }
-
Add the description in
DESCRIPTIONSobject inapp.js.
This project is licensed under the MIT License — see the LICENSE file at the root of the repository for the full text.