This is simply a more complete / working demo of the one Mozilla have made, it acts as simple demostration of the WebAudio API.

The theremin is an oscillator for a given wave function, controlled by the dropdown. The gain (volume) and frequency of the oscillator are controlled by the X and Y position of the mouse pointer over the canvas below. The frequency and gain (X and Y axis) are then used to render and simple visualisation of the current sound onto the canvas.

The whole thing comes in at a little over 100 lines of pure js and a couple of lines HTML. Markup:

<button class="mute">
    mute
</button>
<button class="reset">
    reset
</button>
<select class="type">
    <option value="sine">sine</option>
    <option value="square">square</option>
    <option value="sawtooth">sawtooth</option>
    <option value="triangle">triangle</option>
</select>
<div>
    <canvas style="border:1px solid #000000;"></canvas>
</div>

Code:

var audioCtx = new(window.AudioContext ||
                   window.webkitAudioContext)();

var oscillator = audioCtx.createOscillator(),
    gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

function offset(side, el){
    if(!el)
        return 0;
    return el[side] + offset(side, el.offsetParent);
}

var row = document.querySelector('div.row'),
    canvas = document.querySelector('canvas'),
    canvasCtx = canvas.getContext('2d'),
    WIDTH = row.offsetWidth,
    HEIGHT = window.innerHeight,
    OFFSETLEFT = offset('offsetLeft', canvas),
    OFFSETTOP = offset('offsetTop', canvas),
    maxFreq = 6000,
    maxVol = 1,
    initialFreq = 3000,
    initialVol = 0.5;

// set options for the oscillator
oscillator.type = 'sine';
oscillator.frequency.value = initialFreq; // value in hertz
oscillator.start();

gainNode.gain.value = initialVol;

canvas.width = WIDTH;
canvas.height = HEIGHT;

// Mouse pointer coordinates
var CurX;
var CurY;

// Get new mouse pointer coordinates when mouse is moved
// then set new gain and pitch values
canvas.onmousemove = updatePage;
function updatePage(e) {
    CurX = ((window.Event) ? e.pageX : event.clientX +
        (document.documentElement.scrollLeft ?
         document.documentElement.scrollLeft : document.body.scrollLeft)) -
        OFFSETLEFT;
    CurY = ((window.Event) ? e.pageY : event.clientY +
        (document.documentElement.scrollTop ?
         document.documentElement.scrollTop : document.body.scrollTop)) -
        OFFSETTOP;

    oscillator.frequency.value = (CurX / WIDTH) * maxFreq;
    gainNode.gain.value = (CurY / HEIGHT) * maxVol;

    canvasDraw();
}

function random(number1, number2) {
    var randomNo = number1 +
            (Math.floor(Math.random() * (number2 - number1)) + 1);
    return randomNo;
}

// Render the canvas animation
function canvasDraw() {
    rX = CurX;
    rY = CurY;
    rC = Math.floor((gainNode.gain.value / maxVol) * 30);
    canvasCtx.globalAlpha = 0.2;

    for (i = 1; i <= 15; i = i + 2) {
        canvasCtx.beginPath();
        canvasCtx.fillStyle = 'rgb(' + 100 + (i * 10) + ',' +
            Math.floor((gainNode.gain.value / maxVol) * 255) + ',' +
            Math.floor((oscillator.frequency.value / maxFreq) * 255) + ')';
        canvasCtx.arc(rX + random(0, 50), rY + random(0, 50), rC / 2 + i,
                      (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
        canvasCtx.fill();
        canvasCtx.closePath();
    }
}

var mute = document.querySelector('button.mute');
mute.onclick = function(e) {
    if (mute.id == "") {
        gainNode.disconnect(audioCtx.destination);
        mute.id = "activated";
        mute.innerHTML = "Unmute";
    } else {
        gainNode.connect(audioCtx.destination);
        mute.id = "";
        mute.innerHTML = "Mute";
    }
};

var type = document.querySelector('select');
type.onchange = function(e) {
    oscillator.type = type.value;
};

var reset = document.querySelector('button.reset');
reset.onclick = function(e) {
    oscillator.type = 'sine';
    type.value = 'sine';
    canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
};