neume.js example

HTML

<script src="http://mohayonao.github.io/neume.js/build/neume.min.js"></script>
<canvas id="canvas"></canvas>
<button id="play">play</button>

CSS

#canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}
#play {
    position: absolute;
    top: 15px;
    left: 10px;
    z-index: 999;
}

JavaScript

var Neume = neume(new AudioContext());

var Synth = new Neume(function($, freqs, pan) {
    var out, freq;
    
    freq = $(freqs, { timeConstant: 0.005 });
    
    out = $("sin", { freq: freq, mul: 0.4 });
    out = $("adsr", { a: 0.05, d: 0.15, s: 0.4, r: 1 }, out)
        .release("+2").on("end", function(e) {
            this.stop(e.playbackTime);
        });
    // out = $("comb", { gain: 0.5, ffGain: 0.25, fbGain: 0.5, delay: 0.25 }, out);
    out = $("pan2", { pos: pan }, out);
    
    $.interval("2n", freq.next);
    
    return $("out", { bus: 1 }, out);
});

var Out = new Neume(function($) {
    var out;
    
    out = $("in", 1);
    
    return $("out", { bus: 0 }, out);
});

function playSynth(e) {
    new Synth([ 0, 0, 0, 0 ].map(randomFrequency), randomPosition(0.3, 0.05)).start();
}

function midicps(midi) {
    return 440 * Math.pow(2, (midi - 69) / 12);
}

function randomFrequency() {
     // minor pentatonic
    var scale = [ 0, 3, 5, 7, 10 ];
    
    var index = (Math.random() * 12)|0;
    var midi = scale[index % scale.length] + ((index / scale.length)|0) * 12;
    
    return midicps(midi + 48);
}

function randomPosition(pos, amount) {
    return pos * (Math.random() < 0.5 ? -1 : +1) + (Math.random() * 2 - 1) * amount;
}

var synth = null;
var timer = null;
var reqId = 0;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

canvas.width  = 320;
canvas.height = 320;

function start() {
    Neume.analyser.fftSize = 1024;
    Neume.context.bpm = 108;
    synth = new Out().start();
    timer = new Neume.Interval("4n", playSynth).start();
    reqId = requestAnimationFrame(animate);
}

function stop() {
    synth.fadeOut("+0", 2);
    timer.stop();
    cancelAnimationFrame(reqId);
}

function animate() {
    var data = new Uint8Array(Neume.analyser.fftSize);
    Neume.analyser.getByteFrequencyData(data); 
    
    var m = Math.max(180, Math.max.apply(null, data));
    var x = (Math.random() *...