Skip to content

Instantly share code, notes, and snippets.

@tashian
Last active July 12, 2016 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tashian/2549c6d50893f279f7bfb077747b3494 to your computer and use it in GitHub Desktop.
Save tashian/2549c6d50893f279f7bfb077747b3494 to your computer and use it in GitHub Desktop.

Thoughts on improving Web Audio

Background: I'm working on a project that uses Web Audio API and synthesized sound. This is my first time using Web Audio API and I've struggled to find good sounds. Wishing the current libraries were more accessible to, for example, a game developer who would like to be able to select from a palette of interesting sounds.

With the benefit of an outsider's eye on web audio, I see four issues with synth libs right now:

  1. they aren't opinionated enough. not enough presets, simulations, or good-sounding defaults
  2. documentation is often not playable or tweakable (seems critical for a music lib)
  3. no easy way to twist some knobs and generate sound snippits (JSON?) that I can use in my program
  4. the syntax for many of the libraries feels clunky to me

What's out there

Wad lets you create oscillators w/ASDR, Filters, LFOs, and reverb controls. A lot of work has gone into this library.

  • Includes the Tuna lib and supports Tuna effects for Wads.
  • PolyWads to combine oscillators, filter and pan them together
  • allows playing & filtering wav files, mic input
  • Includes panning & 3D panning support.
  • MIT license

Frustrations: Wad is designed for you to call the constructor once with a single object of settings and filters, then make adjustments to those settings later as needed (eg. while playing each note, or while a note is playing). Therefore you have to learn how to build Wads and, separately, how to control them.

Some demos but no playground.

Lots of functionality but easy to get started. The first lib I've found where you can specify tempo & note lengths:

//trigger "C4" for the duration of an 8th note
synth.triggerAttackRelease("C4", "8n");

Docs and demos could use work. And there's no playground.

Timbre.js provides "functional processing and synthesizing audio in your web apps"

Frustrations: Awkward syntax detract from expressiveness.

T("sin", {freq:880, mul:0.5}).play();

This project defines a JSON structure for import/export of processing graphs, and they have a workbench site SoundIO that will even export these graphs for use in your own project! But it was broken when I tried it.

Seems more focused on playing & filtering wav files than on synthesis.

Outstanding Questions:

  • Tone.js could be a good starting point. Not sure about building another lib on top of it--seems too far from the metal for a real-time application.
  • What do "plugins" look like in this world? eg. "outboard gear"
  • What would great looking code for building & chaining oscillators, filters, effects look like?

Sketches in code

This is just me sketching out some ideas in code, searching for abstractions and expressiveness.

var audo = require('audo');

audo.setGain(0.5); # (a value between 0-1)

# Oscillators:
var sine = new audo.Sine({pitch: audo.C3}) # .. or hz: 440
sine.start(); # play one note
sine.stop();

# Perhaps start() returns a promise?
var listener = sine.start({hold: 0.5}).then(function(sine) {
  console.log('done!');
});

audo.Square()
audo.Sawtooth()
audo.Triangle()

# Single-channel audio buffers:
# default: uses audioCtx.sampleRate when creating an
# AudioBuffer
var duration = 2.0; # seconds
var whiteNoiseGenerator = function(buffer) {
  for (var i = 0; i < buffer.length; i++) {
    # Math.random() is in [0; 1.0]
    # audio needs to be in [-1.0; 1.0]
    buffer[i] = Math.random() * 2 - 1;
  }
  return buffer;
});
# Depending on how we map it later,
# this will either act as a stereo or mono buffer.
var myBuffer = new audo.Buffer(duration, whiteNoiseGenerator);

# To create a stereo buffer, we just need another generator:
var myBuffer = new audo.Buffer(duration, leftChanGenerator, rightChanGenerator);

# Hides AudioBufferSourceNode
myBuffer.start();
myBuffer.stop();

var noise = audo.WhiteNoise();
noise.start();
noise.stop();

# Load from URL
var wavBuffer = new audo.Buffer('http://www.xyz.com/telephone.wav')
wavBuffer.start();
wavBuffer.stop();
wavBuffer.then(function(decodedData) {
  # Play with the data here
});

# Mixing channels
var mixer = new Audo.mixer(left: wavBuffer, right: new audo.WhiteNoise());
mixer.start();
mixer.stop();

# Scheduling...?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment