Created
January 17, 2018 05:49
-
-
Save broady/c07dcc99e47c6c523a19e527261b4bc1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<script> | |
module = {}; | |
</script> | |
<script src="https://cdn.jsdelivr.net/npm/webmidi"></script> | |
<script src="node_modules/beats/index.js"></script> | |
<script> | |
window.onload = function() { | |
navigator.getUserMedia({ | |
audio: true, | |
}, function(stream) { | |
var ctx = new AudioContext(); | |
var sampleRate = ctx.sampleRate; | |
var source = ctx.createMediaStreamSource(stream); | |
var analyser = ctx.createAnalyser(); | |
analyser.fftSize = 2048; // 32768 max | |
source.connect(analyser); | |
var freq2Bin = function(freq) { | |
return Math.floor(freq / (ctx.sampleRate / analyser.fftSize)); | |
}; | |
var bins = [ | |
{ | |
lo: freq2Bin(20), | |
hi: freq2Bin(150), | |
}, | |
{ | |
lo: freq2Bin(150), | |
hi: freq2Bin(450), | |
}, | |
{ | |
lo: freq2Bin(450), | |
hi: freq2Bin(600), | |
}, | |
]; | |
var detector = beats(bins); | |
var squares = [ | |
document.querySelector('#beat'), | |
document.querySelector('#beat2'), | |
document.querySelector('#beat3'), | |
]; | |
var val = document.querySelector('#v'); | |
var midiValues = [0, 0, 0]; | |
var avgFrameRate = 60; | |
var frame = 0; | |
var freqData = new Uint8Array(freq2Bin(1000)); | |
var lastFrame = +new Date; | |
function draw() { | |
requestAnimationFrame(draw); | |
var now = +new Date; | |
avgFrameRate = avgFrameRate * .2 + .8 * (1000 / (now - lastFrame)); | |
frame++; | |
if (frame % 10 == 0) { | |
val.innerText = Math.floor(avgFrameRate) + 'fps'; | |
frame = 0; | |
} | |
analyser.getByteFrequencyData(freqData); | |
var beatData = detector(freqData, now - lastFrame); | |
for (var i = 0; i < squares.length; i++) { | |
if (beatData[i] != 0) { // on beat | |
midiValues[i] = beatData[i] / 255; | |
} else { | |
midiValues[i] = midiValues[i] * .4; // decay | |
} | |
squares[i].style.opacity = midiValues[i]; | |
if (midiOut) { | |
midiOut.sendPitchBend(midiValues[i] - .5, i+1); | |
} | |
} | |
lastFrame = now; | |
} | |
requestAnimationFrame(draw); | |
var midiOut; | |
WebMidi.enable(function(err) { | |
if (err) { | |
alert('WebMidi: '+ err); | |
return; | |
} | |
if (!WebMidi.outputs.length) { | |
console.log('no midi outputs'); | |
return; | |
} | |
var selector = document.querySelector('#midiout'); | |
for (var i = 0; i < WebMidi.outputs.length; i++) { | |
var option = document.createElement('option'); | |
var out = WebMidi.outputs[i]; | |
option.value = out.id; | |
option.label = out.name; | |
selector.appendChild(option); | |
} | |
midiOut = WebMidi.outputs[0]; | |
}); | |
}, function() { | |
alert('please allow audio') | |
}) | |
}; | |
</script> | |
<div id="beat"></div> | |
<div id="beat2"></div> | |
<div id="beat3"></div> | |
<div id="v"></div> | |
freq | |
<input type="range" min="0" max="500" id="freq_slider"> | |
<div id="freq_indicator"></div> | |
Q | |
<input type="range" min="0" max="10" step="0.01" id="q_slider"> | |
<div id="q_indicator"></div> | |
gain | |
<input type="range" min="0.1" max="5" step="0.01" id="gain_slider"> | |
<div id="gain_indicator"></div> | |
<select id="midiout"></select> | |
<style> | |
#beat, #beat2, #beat3 { | |
width: 50px; | |
height: 50px; | |
background: black; | |
display: inline-block; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment