JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
function __fire(e, data) {
log.innerHTML += "\n" + e + " " + (data || '');
}
var audio_context;
var recorder;
var effect_level,
source_level,
delay,
delay_gain,
mix;
function iCanHazUserMedia(stream) {
__fire('I haz live stream');
var input = toMono(audio_context.createMediaStreamSource(stream));
source_level = audio_context.createGain();
effect_level = audio_context.createGain();
effect_level.gain.level = 0.5;
mix = audio_context.createGain();
input.connect(source_level);
input.connect(effect_level);
// delay
delay = audio_context.createDelay();
delay.delayTime.value = 0.6;
delay_gain = audio_context.createGain();
delay_gain.gain.value = 0.3;
delay_gain.connect(delay);
delay.connect(delay_gain);
effect_level.connect(delay);
delay.connect(mix);
source_level.connect(mix);
mix.connect(audio_context.destination);
__fire('input connected to destination');
recorder = new Recorder(mix);
__fire('recorder init\'d');
}
var bufferpool = {};
var loadSound = function(file, name) {
var request = new XMLHttpRequest();
request.open('GET', file, true);
request.responseType = 'arraybuffer';
request.onload = function() {
audio_context.decodeAudioData(request.response, function(buff) {
bufferpool[name] = buff;
});
};
request.send();
};
var playSound = function(sound, when, gain) {
var source = audio_context.createBufferSource();
source.buffer = bufferpool[sound];
if (gain) {
var gain_node = audio_context.createGain();
gain_node.gain.value = gain;
source.connect(gain_node);
gain_node.connect(audio_context.destination);
} else {
source.connect(audio_context.destination);
}
source.start(when);
};
function toMono(input) {
var split = audio_context.createChannelSplitter(2);
var merge = audio_context.createChannelMerger(2);
input.connect(split);
split.connect(merge, 0, 0);
split.connect(merge, 0, 1);
return merge;
}
function startRecording(me) {
recorder && recorder.record();
me.disabled = true;
me.nextSibling.disabled = false;
__fire('recording....');
}
function stopRecording(me) {
recorder && recorder.stop();
me.disabled = true;
me.previousSibling.disabled = false;
__fire('nuff recording');
recorder && recorder.exportWAV(function(blob) {
var url = URL.createObjectURL(blob);
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
au.controls = true;
au.src = url;
hf.href = url;
hf.download = new Date().toISOString() + '.wav';
hf.innerHTML = hf.download;
li.appendChild(au);
li.appendChild(hf);
recordingslist.appendChild(li);
});
recorder.clear();
}
var basic_pattern = {
// 1 2 3 4
hihat: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
snare: [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
kick: [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
};
var rap_pattern = {
// 1 2 3 4
hihat: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
snare: [0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0],
kick: [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]
};
var animid;
var looping = false;
var curr = 0;
function loop() {
looping = !looping;
if (looping) {
pipe();
} else {
clearTimeout(animid);
chordsGoodTill = 0;
goodTill = 0;
curr = 0;
}
}
function pipe() {
scheduleDrums();
scheduleChords();
animid = setTimeout(pipe, 20);
}
var bpm = 86;
var goodTill = 0;
function scheduleDrums() {
var time = audio_context.currentTime;
if (goodTill === 0) { // restart
goodTill = time;
}
if (time + 0.5 < goodTill) {
return;
}
var klik = (60 / bpm) / 4;
time = goodTill;
var pattern = basic_pattern;
for (var i = 0; i < 16; i++) {
Object.keys(pattern).forEach(function(drum) {
if (pattern[drum][i]) {
playSound(drum, time + i * klik, 0.3);
}
});
}
goodTill = time + 16 * klik;
}
var joe = {
name: "Hey Joe",
bpm: 86,
parts: {
verse: [
'C', '/', 'G', '/', 'A', '/', 'D', '/',
'E', '/', '/', '/', '/', '/', '/', '/',
],
},
composition: [
'verse'
],
loop: true
};
var chords = [];
var chords_bpm = 0;
function compile(song) {
console.log(song);
chords = [];
for (var i = 0; i < song.composition.length; i++) {
var part = song.parts[song.composition[i]];
for (var j = 0; j < part.length; j++) {
var ch = part[j];
if (ch === '/' && chords.length) {
ch = chords[chords.length - 1].name;
}
chords.push({
name: ch,
comp: i,
part: j
});
}
}
// add 4 sticks
chords.unshift(1, 2, 3, 4);
chords.foursticks = true;
if (song.loop) {
chords.push(0);
}
chords_bpm = song.bpm;
}
var chordsGoodTill = 0;
function scheduleChords() {
var klik = (60 / bpm) / 2;
var time = audio_context.currentTime;
if (chordsGoodTill === 0) { // restart
chordsGoodTill = time;
}
if (time + klik < chordsGoodTill) {
return;
}
chordsGoodTill = time + klik * 4 + 4;
var chord = chords[curr++];
if (!chord && chord !== 0) {
return stop();
}
if (chord === 0) {
// rm 4 stix and loop
curr = 0;
if (chords.foursticks) {
chords = chords.slice(4);
}
chord = chords[curr++];
}
if (typeof chord === 'number') {
var name = chord;
} else {
var name = chord.name;
}
// show
console.log(curr, name);
}
onload = function() {
try {
// shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
window.URL = window.URL || window.webkitURL
audio_context = new AudioContext;
__fire('Audio context OK');
__fire('navigator.getUserMedia ' + (navigator.getUserMedia ? 'OK' : 'fail'));
loadSound('/uploads/1910/hihat.wav', 'hihat');
loadSound('/uploads/1910/kick.wav', 'kick');
loadSound('/uploads/1910/snare.wav', 'snare');
} catch (e) {
alert('No web audio support in this browser');
}
navigator.getUserMedia({
audio: true
},
iCanHazUserMedia,
function(e) {
__fire('No live audio input ' + e);
}
);
};