Work in progress Fledgetone is still being built, so things may change or break.

Tools Fledge Synth

Fledge Synth

Download fledgetone-fledge-synth.zip (868 KB) README.md

Part of Fledgetone (https://fledgetone.com), © Martin Swanson, GPL-3.0-or-later. Source code: https://github.com/martinmswanson-cmd/fledgetone

Fledgetone's own synthesizer, built to WebAssembly, with a small wrapper so you can play it in any web page or browser game through the Web Audio API.

What's in this zip

FileWhat it is
fledge-synth.jsThe wrapper you import (main thread)
fledge-processor.jsIts AudioWorklet processor, which runs the synth
fledge-choices.jsThe options of the parameters that are choices
fledge.wasmThe synth itself, compiled to WebAssembly
index.htmlAn example page that plays a few notes
source/The synth's Rust source code, to build fledge.wasm yourself
LICENSEThe GNU General Public License, version 3

Try it

Serve this folder and open index.html (AudioWorklets don't run from a file:// page):

npx serve

Use it

import { FledgeSynth } from './fledge-synth.js';

const context = new AudioContext();
const synth = await FledgeSynth.create(context, { preset: 'Lead/Supersaw', tempo: 120 });
const volume = new GainNode(context, { gain: 0.3 });
synth.connect(volume).connect(context.destination);

button.onclick = async () => {
  await context.resume();                         // browsers start sound only after a click
  const t = context.currentTime;
  synth.noteOn('C4', 100, t);                     // a note number (60) or a name, velocity 1 to 127
  synth.noteOff('C4', t + 0.5);
};

synth.setParam('Cutoff', 0.4);                    // every parameter is 0 to 1
synth.setParam('Filter type', 'Ladder');          // a choice also takes its option's name
synth.setParam('Reverb on', true);
await synth.setPreset('Bass/Wobble');

The calls:

CallWhat it does
FledgeSynth.create(context, options?)Makes a synth. Options: preset (name or number), tempo (BPM), wasmUrl, processorUrl
connect(node), disconnect()Where its stereo sound goes. synth.node is the AudioWorkletNode itself
noteOn(note, velocity?, time?), noteOff(note, time?)Play and let go of a note. time is on the audio clock (context.currentTime), now if left out
allNotesOff(time?, hard?)Let every note go (hard: cut them off at once)
pitchBend(amount, time?), modWheel(amount, time?)Bend (-1 to 1) and the mod wheel (0 to 1)
midi(status, data1, data2, time?)Any MIDI message
setParam(name, value, time?), getParam(name)A parameter, 0 to 1 (or an option's name, or true/false)
listParams(), choices(name)The parameters' names; a choice's options
describe()Every parameter now, with the text the synth shows for it ("8.00 kHz")
listPresets(), setPreset(name)The presets; choose one (it sets every parameter)
setTempo(bpm)The tempo the LFOs and the delay keep time with
destroy()Free the synth

It works in an OfflineAudioContext too, to render sound to a buffer.

The synth's own Level parameter starts at -14 dB and a safety clipper keeps every note under -1 dB, but a stack of loud notes can still be loud: keep a volume control after it.

Presets

#PresetIts macros
0Init saw(none)
1Bass/Wobble1: Speed up, 2: Squelch, 3: Grit
2Bass/Growl1: Open, 2: Growl, 3: Grit
3Bass/Riddim1: Squelch, 2: Grit, 3: Growl
4Bass/Detune1: Bright, 2: Spread, 3: Grit
5Bass/Neuro1: Squelch, 2: Morph, 3: Grit
6Bass/Talking1: Open, 2: Squelch, 3: Grit
7Bass/Yoi1: Squelch, 2: Grit, 3: Growl
8Bass/Tearout1: Tear, 2: Grit, 3: Growl
9Bass/Screech1: Speed up, 2: Morph, 3: Grit
10Bass/Sync1: Sync, 2: Bright, 3: Grit
11Bass/Split1: Body, 2: Bite, 3: Grit
12Bass/Sub1: Grit, 2: Tone, 3: Shape
13Bass/808 slide1: Grit, 2: Tone, 3: Shape
14Lead/Supersaw1: Darken, 2: Spread, 3: Space
15Lead/Rave1: Darken
16Lead/Sine1: Grit, 2: Echo
17Lead/Sync1: Morph
18Lead/Fifths1: Bright, 2: Grit
19Lead/Folded1: Fold, 2: Echo
20Lead/Chip1: Crunch
21Keys/Pluck1: Bright, 2: Echo
22Keys/Bell1: Morph, 2: Space
23Keys/Organ1: Tone, 2: Chorus
24Keys/Stab1: Bright, 2: Space
25Chords/Future bass1: Bright, 2: Spread
26Chords/Gated1: Bright, 2: Echo
27Chords/Minor stack1: Bright, 2: Space
28Pad/Dark1: Bright, 2: Space
29Pad/Warm strings1: Bright, 2: Space
30Pad/Shimmer1: Morph, 2: Space
31Pad/Glass1: Morph, 2: Space
32FX/Riser1: Space
33FX/Downlifter(none)
34FX/Laser(none)
35Bass/Talking Growl1: Talk speed, 2: Vowel, 3: Grit
36Bass/Riddim Cell1: Squelch, 2: Grit, 3: Crunch
37Bass/Colour Chord Stab1: Bright, 2: Ring, 3: Grit
38Bass/Neuro Reese1: Comb, 2: Grit, 3: Phase
39Bass/Dive Screech1: Scream, 2: Morph, 3: Grit
40Bass/Clean Sub1: Warmth, 2: Tone, 3: Soften
41Lead/Hardcore Supersaw1: Darken, 2: Drive, 3: Space
42Pad/Wide Wash1: Bright, 2: Space
43Keys/Bright Pluck1: Bright, 2: Echo
44Bass/Crunch Formant1: Vowel, 2: Crunch, 3: Grit
45Bass/Resample Chop1: Slice, 2: Crush, 3: Grit
46Bass/Clipped Square1: Bright, 2: Width, 3: Grit
47Bass/Hard Clip Stab1: Bright, 2: Spread, 3: Grit
48Lead/Chip Crunch1: Crush, 2: Warp
49Bass/Driven Legato1: Bright, 2: Shape, 3: Grit
50Lead/Soaring Saw1: Darken, 2: Spread, 3: Space
51Chords/Silk Stack1: Bright, 2: Drive, 3: Space
52Pad/Silk Wash1: Bright, 2: Space
53Bass/Round Root1: Bright, 2: Shape, 3: Grit
54Keys/Vowel Chop1: Vowel, 2: Space
55Keys/Glass Pluck1: Morph, 2: Space
56FX/Reverse Swell1: Bright, 2: Space

A preset's macros are the parameters Macro 1 to Macro 4: each moves several things at once.

Parameters

Every parameter is a number from 0 to 1. Knobs go from their lowest to their highest setting; switches are off below 0.5 and on above. Starts at is how each is set when a synth is made (before a preset is chosen).

#ParameterKindStarts at
0A onswitchon
1A tablechoiceBasic shapes
2A positionknob0%
3A octaveknob0
4A semitoneknob0 st
5A fineknob0.00 ct
6A levelknob0.0 dB
7A unisonknob1 voices
8A detuneknob25%
9A blendknob70%
10A widthknob50%
11A warpchoiceOff
12A warp amountknob0%
13A phaseknob0%
14A random phaseknob0%
15A stackchoiceOff
16A panknob+0%
17A routechoiceFilter 1
18B onswitchon
19B tablechoiceBasic shapes
20B positionknob0%
21B octaveknob0
22B semitoneknob0 st
23B fineknob0.00 ct
24B levelknob0.0 dB
25B unisonknob1 voices
26B detuneknob25%
27B blendknob70%
28B widthknob50%
29B warpchoiceOff
30B warp amountknob0%
31B phaseknob0%
32B random phaseknob0%
33B stackchoiceOff
34B panknob+0%
35B routechoiceFilter 1
36FM B → Aknob0%
37Sub levelknoboff
38Sub octavechoice−1 octave
39Noise levelknoboff
40Noise routechoiceFilter 1
41Filter typechoiceLow pass 24
42Cutoffknob8.00 kHz
43Resonanceknob15%
44Filter driveknob0%
45Key trackingknob50%
46Filter envelopeknob+0%
47Filter 2 typechoiceLow pass 12
48Filter 2 cutoffknob8.00 kHz
49Filter 2 resonanceknob15%
50Filter 2 key trackingknob50%
51Filter 2 envelopeknob+0%
52Filter 1 into 2switchoff
53Amp attackknob1.20 ms
54Amp decayknob300 ms
55Amp sustainknob100%
56Amp releaseknob120 ms
57Filter attackknob0.40 ms
58Filter decayknob400 ms
59Filter sustainknob0%
60Filter releaseknob200 ms
61Mod env attackknob0.40 ms
62Mod env decayknob500 ms
63Mod env sustainknob0%
64Mod env releaseknob300 ms
65Pitch envelopeknob0.00 st
66Pitch decayknob80.0 ms
67Drive typechoiceOff
68Driveknob0.00 dB
69Drive mixknob100%
70LFO 1 shapechoiceSine
71LFO 1 syncswitchon
72LFO 1 rate (sync)choice1/8
73LFO 1 rate (Hz)knob2.00 Hz
74LFO 1 modechoiceRetrig
75LFO 1 phaseknob0%
76LFO 1 fade inknob1.00 ms
77LFO 1 target 1choiceNone
78LFO 1 amount 1knob+0%
79LFO 1 target 2choiceNone
80LFO 1 amount 2knob+0%
81LFO 2 shapechoiceSine
82LFO 2 syncswitchon
83LFO 2 rate (sync)choice1/8
84LFO 2 rate (Hz)knob2.00 Hz
85LFO 2 modechoiceRetrig
86LFO 2 phaseknob0%
87LFO 2 fade inknob1.00 ms
88LFO 2 target 1choiceNone
89LFO 2 amount 1knob+0%
90LFO 2 target 2choiceNone
91LFO 2 amount 2knob+0%
92LFO 3 shapechoiceSine
93LFO 3 syncswitchon
94LFO 3 rate (sync)choice1/8
95LFO 3 rate (Hz)knob2.00 Hz
96LFO 3 modechoiceRetrig
97LFO 3 phaseknob0%
98LFO 3 fade inknob1.00 ms
99LFO 3 target 1choiceNone
100LFO 3 amount 1knob+0%
101LFO 3 target 2choiceNone
102LFO 3 amount 2knob+0%
103LFO 4 shapechoiceSine
104LFO 4 syncswitchon
105LFO 4 rate (sync)choice1/8
106LFO 4 rate (Hz)knob2.00 Hz
107LFO 4 modechoiceRetrig
108LFO 4 phaseknob0%
109LFO 4 fade inknob1.00 ms
110LFO 4 target 1choiceNone
111LFO 4 amount 1knob+0%
112LFO 4 target 2choiceNone
113LFO 4 amount 2knob+0%
114Shape 1 step 1knob+100%
115Shape 1 step 2knob+100%
116Shape 1 step 3knob-100%
117Shape 1 step 4knob-100%
118Shape 1 step 5knob+50%
119Shape 1 step 6knob+50%
120Shape 1 step 7knob-100%
121Shape 1 step 8knob-100%
122Shape 1 step 9knob+100%
123Shape 1 step 10knob+0%
124Shape 1 step 11knob-100%
125Shape 1 step 12knob+0%
126Shape 1 step 13knob+100%
127Shape 1 step 14knob+50%
128Shape 1 step 15knob+0%
129Shape 1 step 16knob-50%
130Shape 1 smoothknob30%
131Shape 2 step 1knob+100%
132Shape 2 step 2knob-100%
133Shape 2 step 3knob+100%
134Shape 2 step 4knob-100%
135Shape 2 step 5knob+100%
136Shape 2 step 6knob+100%
137Shape 2 step 7knob-100%
138Shape 2 step 8knob-100%
139Shape 2 step 9knob+100%
140Shape 2 step 10knob-100%
141Shape 2 step 11knob+100%
142Shape 2 step 12knob-100%
143Shape 2 step 13knob+100%
144Shape 2 step 14knob-100%
145Shape 2 step 15knob-100%
146Shape 2 step 16knob-100%
147Shape 2 smoothknob10%
148Mod 1 sourcechoiceNone
149Mod 1 targetchoiceNone
150Mod 1 amountknob+0%
151Mod 2 sourcechoiceNone
152Mod 2 targetchoiceNone
153Mod 2 amountknob+0%
154Mod 3 sourcechoiceNone
155Mod 3 targetchoiceNone
156Mod 3 amountknob+0%
157Mod 4 sourcechoiceNone
158Mod 4 targetchoiceNone
159Mod 4 amountknob+0%
160Mod 5 sourcechoiceNone
161Mod 5 targetchoiceNone
162Mod 5 amountknob+0%
163Mod 6 sourcechoiceNone
164Mod 6 targetchoiceNone
165Mod 6 amountknob+0%
166Mod 7 sourcechoiceNone
167Mod 7 targetchoiceNone
168Mod 7 amountknob+0%
169Mod 8 sourcechoiceNone
170Mod 8 targetchoiceNone
171Mod 8 amountknob+0%
172Macro 1knob0%
173Macro 2knob0%
174Macro 3knob0%
175Macro 4knob0%
176VoiceschoicePoly
177Glideknob1.00 ms
178Bend rangeknob2 st
179Velocityknob50%
180EQ onswitchoff
181EQ lowknob0.00 dB
182EQ low freqknob120 Hz
183EQ midknob0.00 dB
184EQ mid freqknob1.00 kHz
185EQ highknob0.00 dB
186EQ high freqknob6.00 kHz
187Chorus onswitchoff
188Chorus rateknob0.60 Hz
189Chorus depthknob50%
190Chorus mixknob40%
191Phaser onswitchoff
192Phaser modechoicePhaser
193Phaser rateknob0.30 Hz
194Phaser depthknob70%
195Phaser feedbackknob50%
196Phaser mixknob50%
197Delay onswitchoff
198Delay syncswitchon
199Delay time (sync)choice1/8.
200Delay time (ms)knob300 ms
201Delay feedbackknob35%
202Delay ping-pongswitchon
203Delay toneknob6.00 kHz
204Delay mixknob25%
205Reverb onswitchoff
206Reverb sizeknob60%
207Reverb decayknob2.50 s
208Reverb toneknob7.00 kHz
209Reverb pre-delayknob10.0 ms
210Reverb mixknob25%
211OTTknob0%
212OTT timeknob60%
213Widthknob40%
214Levelknob-14.0 dB
215LFO 1 retriggerchoiceAs the voices
216LFO 1 delayknoboff
217LFO 1 smoothknob0%
218LFO 1 key trackingknob0%
219LFO 1 sustain pointknob50%
220LFO 2 retriggerchoiceAs the voices
221LFO 2 delayknoboff
222LFO 2 smoothknob0%
223LFO 2 key trackingknob0%
224LFO 2 sustain pointknob50%
225LFO 3 retriggerchoiceAs the voices
226LFO 3 delayknoboff
227LFO 3 smoothknob0%
228LFO 3 key trackingknob0%
229LFO 3 sustain pointknob50%
230LFO 4 retriggerchoiceAs the voices
231LFO 4 delayknoboff
232LFO 4 smoothknob0%
233LFO 4 key trackingknob0%
234LFO 4 sustain pointknob50%
235Chaos rate (sync)choice1/16
236Chaos smoothknob0%
237Random repeatchoice1 bar
238Mod 9 sourcechoiceNone
239Mod 9 targetchoiceNone
240Mod 9 amountknob+0%
241Mod 10 sourcechoiceNone
242Mod 10 targetchoiceNone
243Mod 10 amountknob+0%
244Mod 11 sourcechoiceNone
245Mod 11 targetchoiceNone
246Mod 11 amountknob+0%
247Mod 12 sourcechoiceNone
248Mod 12 targetchoiceNone
249Mod 12 amountknob+0%
250Mod 13 sourcechoiceNone
251Mod 13 targetchoiceNone
252Mod 13 amountknob+0%
253Mod 14 sourcechoiceNone
254Mod 14 targetchoiceNone
255Mod 14 amountknob+0%
256Mod 15 sourcechoiceNone
257Mod 15 targetchoiceNone
258Mod 15 amountknob+0%
259Mod 16 sourcechoiceNone
260Mod 16 targetchoiceNone
261Mod 16 amountknob+0%
262Mod 1 curvechoiceLinear
263Mod 1 viachoiceNone
264Mod 2 curvechoiceLinear
265Mod 2 viachoiceNone
266Mod 3 curvechoiceLinear
267Mod 3 viachoiceNone
268Mod 4 curvechoiceLinear
269Mod 4 viachoiceNone
270Mod 5 curvechoiceLinear
271Mod 5 viachoiceNone
272Mod 6 curvechoiceLinear
273Mod 6 viachoiceNone
274Mod 7 curvechoiceLinear
275Mod 7 viachoiceNone
276Mod 8 curvechoiceLinear
277Mod 8 viachoiceNone
278Mod 9 curvechoiceLinear
279Mod 9 viachoiceNone
280Mod 10 curvechoiceLinear
281Mod 10 viachoiceNone
282Mod 11 curvechoiceLinear
283Mod 11 viachoiceNone
284Mod 12 curvechoiceLinear
285Mod 12 viachoiceNone
286Mod 13 curvechoiceLinear
287Mod 13 viachoiceNone
288Mod 14 curvechoiceLinear
289Mod 14 viachoiceNone
290Mod 15 curvechoiceLinear
291Mod 15 viachoiceNone
292Mod 16 curvechoiceLinear
293Mod 16 viachoiceNone
294Pre drive typechoiceOff
295Pre driveknob0.00 dB
296Pre drive mixknob100%
297Pre drive crushknob50%
298Drive crushknob50%
299Drive toneknob0%
300Band drive typechoiceOff
301Band driveknob0.00 dB
302Band drive mixknob100%
303Band drive crushknob50%
304Band drive toneknob0%
305Band low splitknob150 Hz
306Band high splitknob2.50 kHz
307Band high amountknob100%
308Sub pathchoiceClean, after effects
309Glide modechoiceAlways
310Glide ratechoiceConstant time
311Glide curvechoiceExponential
312Pitch envelope curvechoiceExponential
313Mono restartswitchon
314Mono belowknob180 Hz
315Random by stepswitchon
316Even keyboardswitchon
317Detune key trackingknob50%

Choices

These parameters are choices. Set them by the option's name, for example synth.setParam('LFO 1 shape', 'Wobble').

Build fledge.wasm yourself

The synth is written in Rust, with no dependencies. In source/:

rustup target add wasm32-unknown-unknown
./build.sh                 # writes ../../public/fledgetone-plugins/fledge.wasm in Fledgetone's repository
cargo test --release       # the synth's tests

Outside Fledgetone's repository, run the build line from build.sh and take the file from target/wasm32-unknown-unknown/release/fledge_synth.wasm. The module has no imports and exports the plain C functions listed in source/src/abi.rs, which fledge-processor.js calls.

Licence

These files are free software under the GNU General Public License, version 3 or (at your choice) any later version: GPL-3.0-or-later. The full text is in LICENSE. In plain words:

This is a summary to help you; the licence text in LICENSE is what counts. Questions or concerns: email martin@twobirdsworkshop.com.