Emmett Corman has a great introductory series on the basics of synthesis (using modular synths), called Simple Synthesis. I thought it would be of value to those without access to the hardware to be able to explore and interact with the concepts that Emmett covers directly in the browser, using the Web MIDI and Web Audio APIs.
In this complementary series, I’ll cover each synthesis topic and show you how to build various synth modules right in your browser. Play, edit, and combine the code to make your own web-based modular synth!
VCO/VCA = OscillatorNode/GainNode
The VCO and VCA have corresponding methods in the Web Audio API: the OscillatorNode and the GainNode. The OscillatorNode has one output which you can connect to any number of inputs and a couple of AudioParams that you can think of as CV inputs: ‘frequency’ and ‘detune’, along with the ‘type’ parameter for selecting different waveforms. The GainNode has one input and one output, which can similarly connect to any number of inputs/outputs, as well as its own ‘CV’ input, the ‘gain’ AudioParam.
Since we’re working in the web browser our keyboard will be connected via Web MIDI. We’re primarily concerned with two functions; noteOn() and noteOff(), which we’ll look at soon.
Let’s connect our patch together following Emmett’s outlined steps:
1. Patch from the VCO output into the VCA signal input
2. Patch from the Keyboard note output into the VCO CV input
This line of code sets the frequency of our VCO and lives inside the noteOn() function which handles our MIDI note-on messages.
3. Patch from the VCA output into a speaker
4. Patch from the keyboard gate output into the VCA CV input (we’re dividing our key velocity by its max value to get a 0 – 1 gain range)
Those are our basic connections, but if we just used the code above we would have no velocity control and hear a lot of popping when changing notes. Let’s take a closer look at our
noteOff() functions to see how we can improve our patch.
By default, when you change an oscillator’s frequency you will get a portamento effect, because every time you change the frequency value it starts at the point it was last set to. If you want clean notes, you will have to use AudioParam scheduling with the clearly named methods
setValueAtTime(value, time). Whenever you useAudioParam scheduling, you need to call
cancelScheduledValues(time) when manually changing an AudioParam, like pressing a key to change frequency or gain. On noteOn, we immediately cancel any values that have been scheduled for that AudioParam and then set our new value from our
frequencyFromNote(MIDINote) function. On noteOff, we can also follow this pattern of cancel and schedule. Although not required, I’ve found that you get a more consistent note when you set the note frequency on noteOff.
Lastly, to smooth out when our notes turn off, I’m keeping track of all active notes in a
activeKeys object, adding the current note(s) to the object on
noteOn() and deleting released notes on
That’s all it takes to get a simple monophonic keyboard, VCO, VCA patch going. Explore the code to get a more thorough understanding of what’s going on.