A quick demo of custom waveforms using the OscillatorNode.setPeriodicWave() and AudioContext.createPeriodicWave() methods of the Web Audio API. Waveforms are defined by Fourier coefficients of the Fourier series that defines the periodic waveform, see here. It is necessary to pass two arrays of type Float32Array, of identical length, as the real (cosine) and imaginary (sine) coefficients of the desired waveform.
The oscilloscope provides a visual representation of the output of the OscillatorNode. The triggering system is necessary because simply drawing the data returned by AnalyserNode.getByteTimeDomainData() results in garbage because the waveform buffer will not consistently start in the same place relative to the waveform.
Keymaps can be selected, and provide varying ways to map the QWERTY keyboard to note values.

Click to Capture Keyboard Focus

Here's a nickel, kid. Go buy yourself a real browser.