Timbre.js

JavaScript Library for Objective Sound Programming
system requirements: Chrome 14- or Firefox 4-
You can operate music with your WebConsole. read

!! Caution !!

if you dump the `dist` or `delay`,
etc in Firefox WebConsole, presumably browser crashes!!

distc.off(), 0; <= you must not forget to add ", 0"

Rhythm

  • beat  = [number] (default= 8)
  • piano = [number] (default= 4)
  • melo  = [number] (default=16)

Distortion

  • dist.on() / dist.off()
  • dist.pre  = [number] : preGain (default=  0dB)
  • dist.post = [number] : postGain(default=-18dB)
  • dist.freq = [number] : lpf.freq(default=2400Hz)
  • dist.mul  = [number] : volume  (default=0.5)

Delay

  • delay.on() / delay.off()
  • delay.time = [number] : delayTime(default=125msec)
  • delay.fb   = [number] : feedback (default=0.8 )
  • delay.wet  = [number] : wet      (default=0.25)
  • delay.mul  = [number] : volume   (default=0.5 )
// load wav files and decode

timbre.workerpath = "../timbre.js";
timbre.utils.exports("converter"); // use atof

// dac
var ex0 = T("dac");

// metronome
var metronome = T("interval", function() {
    metronome.count %= 16 * 4;
});

// amen (load a wav file and decode it)
var amen = T("wav", "./public/audio/amen.wav", true).load(function(res) {
    metronome.interval = (this.duration / 3) / 16;
});
dist = T("efx.dist", 0, -18, 2400, amen).set("mul", 0.5);
dist.dac = ex0;

var beat = 8, beattimer = (function() {
    var tim = 0, cnt = 0, stay = 0;
    return T("interval", function() {
        if (cnt === 0) {
            if (stay === 0) {
                tim = ((Math.random() * beat)|0) * (amen.duration / beat);
                cnt  = (((Math.random() * beat) / 16)|0) * 2;
                stay = (((Math.random() * beat) /  6)|0);
                amen.currentTime = tim;
            } else {
                stay -= 1;
            }
        } else {
            amen.currentTime = tim;
            cnt -= 1;
        }
    });
}());


// piano chord (load s wav file and decode it)
var piano = 4, pianotimer = (function() {
    var synth, prev_chord, chordtable = [
        [1, 6, 8], [2, 5, 8], [1, 4, 8], [0, 2, 6],
    ], amptable = [ 0.9, 0.5, 0.8, 0.6 ], pianotones = [];
   
    T("wav", "./public/audio/piano_cmaj.wav").load(function(res) {
        var dx = this.duration / 9;
        for (var i = 0; i < 9; i++) {
            pianotones[i] = this.slice(dx * i, dx * i + dx);
        }
    });

    synth = T("+").set("mul", 0.5);
    ex0.append(synth);
    
    function play_chord(chord, amp) {
        if (!chord) return;
        for (var i = 0; i < chord.length; i++) {
            synth.append(pianotones[chord[i]].clone().set("mul", amp));
        }
        while (synth.args.length > 3) {
            synth.args.shift();
        }
    }
    
    return T("interval", function() {
        var chord, amp;
        chord = (metronome.count / 16)|0;
        if (chord !== prev_chord) {
            amp = 1.0; prev_chord = chord;
        } else amp = amptable[metronome.count % 4];
        play_chord(chordtable[chord], amp);
    });
}());

// melo
var leadtone = timbre.utils.wavb(/* define wavetable */);

var lead = T("rlpf", T("pulse", 0.462, 800, 2000, 0.8).kr(),
               0.8, 0.8,
               T("*", T("+", T("osc", leadtone, 0, 0.20),
                             T("osc", leadtone, 0, 0.15)),
                      T("adsr", 20, 1500, 0.4)));
delay = T("efx.delay", 125, 0.8, lead).set("mul", 0.5);
delay.dac = ex0;

var melo = 16, melotimer = (function() {
    var tone1, tone2, env, phrase = [
        0, 0, 0, 0,
        atof("E4"), atof("E4"), atof("A4"),
        atof("A4"), atof("G4"), atof("C5"), ];
    
    tone1 = lead.args[0].args[0].args[0];
    tone2 = lead.args[0].args[0].args[1];
    env   = lead.args[0].args[1];
    
    return T("interval", function() {
        var freq = phrase[(Math.random() * phrase.length)|0];
        if (freq !== 0) {
            tone1.freq.value = freq;
            tone2.freq.value = freq * 0.9928057204912689;
            env.bang();
        }
    });
}());

ex0.onbang  = function() {
    dist.isOn  ? dist.off()  : dist.on();
    delay.isOn ? delay.off() : delay.off();
};
ex0.onplay  = function() {
    metronome.on();
    beattimer.interval  = (amen.duration / 3) / beat;
    beattimer.on();
    pianotimer.interval = (amen.duration / 3) / piano;
    pianotimer.on();
    melotimer.interval  = (amen.duration / 3) / melo;
    melotimer.on();
};
ex0.onpause = function() {
    melotimer.off();
    pianotimer.off();
    beattimer.off();
    metronome.off();
};
       
ex0.play();