Skip to content

Instantly share code, notes, and snippets.

@caillou
Last active Aug 29, 2015
Embed
What would you like to do?
// https://github.com/caillou/motion-synth
// If you have a computer, open the
// dev tools and type this:
ctx = new AudioContext();
osc = ctx.createOscillator();
// Try 'triange', 'sawtooth', 'sine'
osc.type = 'square';
// Try any integer between
// 0 and 18'000
osc.frequency.value = '55';
osc.start();
osc.connect(ctx.destination);
var NOTES = (function () {
var notes = {};
var toneSymbols = "CcDdEFfGgAaB";
function noteToFrequency (note) {
return Math.pow(2, (note-69)/12)*440;
}
for (var octave = 0; octave <= 10; ++octave) {
for (var t = 0; t < 12; ++t) {
notes[octave*12+t] = notes[toneSymbols[t]+octave] = noteToFrequency(octave * 12 + t);
}
}
return notes;
}());
var out = ctx.createGain();
var osc = ctx.createOscillator();
osc.type = 'square';
var lfo = ctx.createOscillator();
lfo.frequency.value = 2;
var lfoGain = ctx.createGain();
lfoGain.gain.value = 55;
lfo.start()
lfo.connect(lfoGain);
osc.frequency.value = 110
lfoGain.connect(osc.frequency);
osc.connect(out);
out.connect(ctx.destination);
osc.start(ctx.currentTime);
createDrone = function (out) {
[
// {t: 'sawtooth', f: 27.5, g: 0.82},
{t: 'sawtooth', f: 55, g: 0.62},
{t: 'sawtooth', f: 110, g: 0.27},
{t: 'sawtooth', f: 220, g: 0.17},
{t: 'sawtooth', f: 440, g: 0.10},
{t: 'sawtooth', f: 880, g: 0.05},
{t: 'sawtooth', f: 1760, g: 0.02},
{t: 'sawtooth', f: 3520, g: 0.005},
{t: 'sawtooth', f: 7040, g: 0.004}
].forEach(function (o, i) {
var type, frequency, delta;
type = o.t;
frequency = o.f;
delta = o.d;
var osc, gain;
osc = ctx.createOscillator();
gain = ctx.createGain();
gain.connect(out);
gain.gain.value = o.g/2;
osc.connect(gain);
osc.type = type;
osc.frequency.value = frequency;
osc.start(ctx.currentTime);
f2 = frequency + (frequency / 50 * Math.random());
osc2 = ctx.createOscillator();
osc2.connect(gain);
osc2.type = type;
osc2.frequency.value = f2;
osc2.start(ctx.currentTime);
f2 = frequency + (frequency / 30 * Math.random());
osc2 = ctx.createOscillator();
osc2.connect(gain);
osc2.type = type;
osc2.frequency.value = f2;
osc2.start(ctx.currentTime);
})
}
var midiEventControll = {};
_.extend(midiEventControll, Backbone.Events);
var midiEventNoteOn = {};
_.extend(midiEventNoteOn, Backbone.Events);
var midiEventNoteOff = {};
_.extend(midiEventNoteOff, Backbone.Events);
setTimeout(function () {
var p = navigator.requestMIDIAccess();
var inputName = function (midiInput) {
return [midiInput.manufacturer, midiInput.name, midiInput.id].join(' ');
};
var onMidiMessage = function (e) {
// debugger
if (e.data[0] == 176) {
midiEventControll.trigger(e.data[1], e.data[2]);
return;
}
if (e.data[0] == 144) {
midiEventNoteOn.trigger(e.data[1], e.data[2]);
return;
}
if (e.data[0] == 128) {
midiEventNoteOff.trigger(e.data[1], e.data[2]);
return;
}
};
p.then(function (access) {
console.log('got access');
var entries = access.inputs.entries();
var entry;
while(!(entry = entries.next()).done) {
var midiInput = entry.value[1];
window.midiInput = midiInput
midiInput.addEventListener('midimessage', onMidiMessage);
midiInput.addEventListener('disconnect', function () {
console.log(arguments)
});
}
});
}, 2000);
// ADSR
function noteEnvelope (gainNode, time, volume, a, d, s, r) {
var gain = gainNode.gain;
var ctx = gainNode.context;
gain.cancelScheduledValues(0);
gain.linearRampToValueAtTime(volume, time);
gain.linearRampToValueAtTime(volume * s, time + a + d);
return function () {
gain.cancelScheduledValues(0);
gain.setValueAtTime(gain.value, ctx.currentTime);
gain.linearRampToValueAtTime(0, ctx.currentTime + r);
};
}
var out = ctx.createGain();
out.connect(ctx.destination);
out.gain.value = 0;
var osc = ctx.createOscillator();
osc.start(ctx.currentTime);
osc.type = 'square';
osc.frequency.value = 55;
osc.connect(out);
var lfo = ctx.createOscillator();
lfo.frequency.value = 7;
var lfoGain = ctx.createGain();
lfoGain.gain.value = 0;
lfo.start()
lfo.connect(lfoGain);
lfoGain.connect(osc.frequency);
var notes = [
58.27047018976124,
65.40639132514966,
77.78174593052023,
87.30705785825097,
92.4986056779086,
97.99885899543733,
116.54094037952248,
123.47082531403103,
130.8127826502993,
]
var sequences = [
[
{note:1, duration: 1, steps: 1},
{note:2, duration: 1, steps: 1.1},
{note:3, duration: 1, steps: 1.1},
{note:4, duration: 1, steps: 0.8},
{note:5, duration: 1, steps: 1},
{note:5, duration: .6, steps: 1.1},
{note:5, duration: .5, steps: 1.1},
{note:5, duration: .5, steps: 0.8},
{note:8, duration: 0.2, steps: 1}
],
[
{note:2, duration: 1, steps: 1},
{note:4, duration: 1, steps: 1.1},
{note:6, duration: 1, steps: 1.1},
{note:7, duration: 1, steps: 0.8},
{note:8, duration: 1, steps: 1}
],
{note:0, duration: 2, steps: 4}
]
var a = 0.01,
d = 0.2,
s = 0.6,
r = 0.3;
var step = 250;
var playNote = function (note, time) {
if (end.isFulfilled()) return;
var release;
setTimeout(function () {
lfoGain.gain.cancelScheduledValues(0);
lfoGain.gain.value = 0
lfoGain.gain.linearRampToValueAtTime(0, ctx.currentTime + a + d);
lfoGain.gain.linearRampToValueAtTime(10, ctx.currentTime + a + 2*d);
osc.frequency.value = notes[note.note];
release = noteEnvelope(out, ctx.currentTime, 0.6, a, d, s, r)
}, time),
setTimeout(function () {
release()
}, time + (note.duration*step))
}
var triggerSequence = function () {
if (end.isFulfilled()) return;
var time = 0;
sequences[0].forEach(function (note) {
playNote(note, time);
time += step * note.steps;
})
sequences[0].forEach(function (note) {
playNote(note, time);
time += step * note.steps;
})
for (var i = 0; i < 4; i++) {
var length = sequences[1].length;
var noteIndex = Math.floor(Math.random() * length);
var note = sequences[1][noteIndex];
playNote(note, time);
time += step * note.steps;
}
playNote(sequences[2], time);
time += step * sequences[2].steps;
setTimeout(triggerSequence, time);
}
triggerSequence();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment