JavaScript Marathon
Web Audio API
There are many ways to interact with the user in a web application. You could render data to the DOM, or even render 3D visuals using WebGL and the canvas element.
This repo shows a simple example of how to manipulate the Web Audio API to create sounds using the browser's built in synthesizer.
Stack
- NextJS
- TypeScript
- ESLint/Prettier
- TailwindCSS
Important Links
- Repo
- Deployment
- VanillaJS Keyboard Example from MDN
What is the Web Audio API?
From MDN
"The Web Audio API provides a powerful and versatile system for controlling audio on the Web, allowing developers to choose audio sources, add effects to audio, create audio visualizations, apply spatial effects (such as panning) and much more."
The Web Audio API was designed to allow modular routing. What this means is that as the developer, you create and link together different audio nodes to create an audio routing graph.
Linking together different chains of audio nodes is what gives developers the flexibility to create complex audio effects.
Basic Workflow
- Create audio context
- Create audio sources within audio context (this repo uses OscillatorNodes)
- Create effects, such as reverb, biquad filter, or gain
- Select final destination for audio
- Connect sources to effects and effects to destination
Audio Context
The starting point for manipulating sounds with the Web Audio API is the Audio Context. Here is how to create one.
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
We need the portion with window.webkitAudioContext
in order to support Safari and older versions of chrome.
Generally speaking, your application should only ever have one context per page. Since this application uses React, you'll find the Audio Context within the React Context that the app uses throughout the application.
Oscillator Nodes
Main Types of Oscillator Nodes
Oscillator Nodes come in 4 different OscillatorType's
- sine: the default value, these are pure, single-frequency, sound waves
- triangle: made up of an infinite set of odd harmonic sine waves
- square: also made up of an infinite set of odd harmonic sine waves, with upper harmonic amplitudes higher than triangle waves.
- sawtooth: made up of an infinite set of harmonic sine waves waves.
As you go down the list, the different waves make progressively "buzzier" sounds as the waveforms become made up of more and more sound waves.
How to create an Oscillator Node
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const sinewave = audioContext.createOscillator();
sinewave.type = "sine";
sinewave.frequency.value = 440; // A4
sinewave.start();
// sinewave.stop();
Gain Nodes
What are Gain Nodes?
Gain nodes are responsible for manipulating the amplitude of audio sources.
How to create and use a Gain Node
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// Create sine OscillatorNode
const sinewave = audioContext.createOscillator();
sinewave.type = "sine";
sinewave.frequency.value = 440; // A4
// Create and create audio node chain
// OscillatorNode -> GainNode -> Destination
const gainNode = audioContext.createGain();
gainNode.gain.value = 0.5;
sinewave.connect(gainNode)
gainNode.connect(audioContext.destination);
sinewave.start();
This app connects every single OscillatorNode created by the keyboard to a single GainNode which controls the volume of them all.
Wave Shaper Nodes
What are Wave Shaper Nodes?
According to MDN:
The WaveShaperNode interface represents a non-linear distorter. It is an AudioNode that uses a curve to apply a wave shaping distortion to the signal.
Where is this used?
This application uses the WaveShaperNode
interface as part of the synthesis of the snare drum. It's used to gradually lower the amplitude of the pair of triangle waves used to generate the snare.
Bi-Quad Filter
What is the Bi-Quad Filter
MDN says:
The BiquadFilterNode interface represents a simple low-order filter, and is created using the BaseAudioContext/createBiquadFilter method. It is an
AudioNode
that can represent different kinds of filters, tone control devices, and graphic equalizers.
This app used the WaveShaperNode
to help synthesize the snare drum, but the Biquad Filter could have been used as well.
NextJS/Tailwind Starter
If you would like to get a fast start on using this stack, fork my repo and get started with a working "Hello, World!" template today!
Tools included:
- NextJS
- TypeScript
- TailwindCSS
- ESLint/Prettier
- Husky pre-commit linting
Repo: https://github.com/mastapegs/linted-nextjs-tailwind-starter