var bufferSize = 65536 / 2; var sampleRate = 44100; var latency = 1000 * bufferSize / sampleRate; var audioletReady = false; var samples = [ 'KickDrum0001.wav', // 'Closed Hihat0001.wav', 'Open Hihat0001.wav', 'Clap.wav' // 'Clav.wav', 'Mid Tom0001.wav', 'Rimshot.wav', 'SnareDrum0001.wav' ]; function Sampler (audiolet, url) { var base = this; this.audiolet = audiolet; // first get the sample and load it into a buffer var buffer = new AudioletBuffer(1, 0); buffer.load(sample, false); // connect the buffer to a player and set up the objects we need this.trigger = new TriggerControl(this.audiolet); this.player = new BufferPlayer(this.audiolet, buffer, 1, 0, 0); this.gain = new Gain(this.audiolet, 0.80); // trigger -> player -> gain -> OUTPUT trigger.connect(player, 0, 1); player.connect(gain); gain.connect(this.audiolet.output); this.mute = function(){ base.gain.setValue(0); } this.unmute = function(){ base.gain.setValue(0.80); } } function Sequencer (audiolet, instrument) { var base = this; this.instrument = instrument; this.pattern = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; // building a sequencer ... // this makes each note a sixteenth note, and sets up an empty bar var durations = new PSequence([0.25], Infinity); var sequence = new PSequence(this.pattern, Infinity); this.audiolet.scheduler.play([sequence], durations, trigger); function trigger (note, duration) { if (note == 1) { this.instrument.trigger.setValue(1); } } } function AudioletApp () { this.audiolet = new Audiolet(sampleRate, 2, bufferSize); this.audiolet.scheduler.setTempo(90); this.sequencers = []; for (var i in samples) { var sample = "/wav/" + samples[i]; var sampler = new Sampler(this.audiolet, sample); var sequencer = new Sequencer(this.audiolet, sampler); this.sequencers.push(sequencer); } } function Grid (app){ var base = this; function setNote (data) { pattern[data.step][data.channel] = data.state; drawNote(data.step, data.channel); }; base.setBeat = function(beatId) { beat = beatId; }; base.setTempo = function(tempo) { tick = tempo; } base.toggle = toggle; var Audio = new AudioletApp(); var tog = 0; var playing = false; var playingInterval = false; var tick = 125; var pattern = undefined; var channels = []; var channelsOn = []; var activecoloron = 'rgb(255,255,255)'; var activecoloroff = 'rgb(202,202,202)'; var inactivecoloron = 'rgb(152,152,152)'; var inactivecoloroff = 'rgb(28,28,28)'; var gridSize = Math.floor(600/16); var lastStep = 16; var channelCount = 8; var beat = lastStep-1; var inset = 5; var canvas = document.getElementById('canvas'); //.offset(); var ctx = canvas.getContext('2d'); init(); function init(){ bind(); load(); } function bind(){ app.receive("event-grid", loadGrid); app.receive("event-note", setNote); $('#start').click(start); $('#stop').click(stop); $('#tempo').change(function() { resetTempo( document.getElementById('tempo').value ) }); $('#canvas').click(function(e){ var x = e.pageX-canvas.offsetLeft-10; var y = e.pageY-canvas.offsetTop-10; x = Math.floor(x / gridSize); y = Math.floor(y / gridSize); toggleNote(x, y); app.send("event-note", { 'step': x, 'channel': y, 'state': pattern[x][y] }); }); } function loadGrid(data){ pattern = data.pattern; tempo = data.tempo; stop(); start(); } function load(){ if (playing) { playingInterval = setInterval(make, tick); } makeGrid(); } function toggle(){ playing ? stop() : start(); } function start() { reset(); playing = true; load(); document.body.bgColor = "#000000"; for (var i = 0; i < channelCount; i++) { channels[i] = document.getElementById('sound' + i); channelsOn[i] = false; } for (var i = 0; i < channelCount; i++) { channels[i+8] = document.getElementById('sound' + i + 'a'); } } function stop() { playing = false; document.body.bgColor = "#444444"; for (var i = 0; i < channelCount; i++) { document.getElementById('sound' + i).pause(); document.getElementById('sound' + i + 'a').pause(); } reset(); } function reset() { clearInterval(playingInterval); ctx.clearRect(0,0, canvas.width, canvas.height); beat = lastStep-1; } function resetTempo(tempo) { if (tempo <= 1 || tempo >= 800) { tempo = 120; } tick = (1000 / (tempo / 60))/4; $("#alertDisp").html( "Set tempo to " + tempo ); if (playing) { clearInterval(playingInterval); playingInterval = setInterval(make, tick); } } function make() { beat += 1; if (beat == lastStep) { makeColumn(beat-1,activecoloroff,inactivecoloroff,false); beat = 0; makeColumn(beat,activecoloron,inactivecoloron,true); } else { makeColumn(beat,activecoloron,inactivecoloron,true); makeColumn(beat-1,activecoloroff,inactivecoloroff,false); } } function makeColumn(x,active,inactive,goplaysample) { for (var y = 0; y < channelCount; y += 1) { if (pattern[x][y] == 1) { if (goplaysample === true) { // ctx.fillStyle = active; ctx.fillStyle = random_color(); var tmpAudio; if (channelsOn[y] == true) { channelsOn[y] = false; tmpAudio = channels[y+8]; } else { tmpAudio = channels[y]; } tmpAudio.currentTime = 0; if (tmpAudio.paused) tmpAudio.play(); } else { ctx.fillStyle = active; } ctx.fillRect((x*gridSize) + inset, (y*gridSize) + inset, gridSize - 2*inset, gridSize - 2*inset); } else { ctx.fillStyle = inactive; } } } function makeGrid() { for (var x = 0; x < lastStep; x += 1) { for (var y = 0; y < channelCount; y += 1) { if (pattern && pattern[x][y] == 1) { ctx.fillStyle = activecoloroff; } else { ctx.fillStyle = inactivecoloroff; } ctx.fillRect((x*gridSize) + inset, (y*gridSize) + inset, gridSize - 2*inset, gridSize - 2*inset); } } } function drawNote(x,y) { if (pattern[x][y] == 1) { ctx.fillStyle = activecoloroff; } else { ctx.fillStyle = inactivecoloroff; } ctx.fillRect((x*gridSize) + inset, (y*gridSize) + inset, gridSize - 2*inset, gridSize - 2*inset); } function toggleNote(x,y) { if (pattern[x][y] == 1) { pattern[x][y] = 0; } else { pattern[x][y] = 1; } drawNote(x,y); } function random_color() { var rint = Math.round(0xffffff * Math.random()); return 'rgb(' + (rint >> 16) + ',' + (rint >> 8 & 255) + ',' + (rint & 255) + ')'; } };