Last active
August 29, 2015 13:56
-
-
Save houkanshan/9036745 to your computer and use it in GitHub Desktop.
microphone demo.
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> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title></title> | |
</head> | |
<body> | |
<canvas></canvas> | |
<span class="count"></span> | |
<script> | |
var module = { exports: {} } | |
</script> | |
<script src="./mainloop.js"></script> | |
<script src="./virtualizer.js"></script> | |
<script src="./kick-detector.js"></script> | |
<script src="./microphone.js"></script> | |
<script src="./index.js"></script> | |
</body> | |
</html> |
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
var microphone = new Microphone({ process: true }) | |
var mainLoop = new MainLoop() | |
var virtualizer = new Virtualizer() | |
var kickDetector = new KickDetector() | |
virtualizer.getArray = function() { | |
return microphone.getFreqs() | |
} | |
var array = [] | |
microphone.defaultProcessor.onaudioprocess = function(e) { | |
array = e.inputBuffer.getChannelData(0) | |
} | |
kickDetector.getArray = function() { | |
//return microphone.getTimes() | |
return array | |
} | |
//mainLoop.addSpirit(virtualizer) | |
mainLoop.addSpirit(kickDetector) | |
mainLoop.start() | |
microphone.capture() |
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
function addAll(array) { | |
var total = 0 | |
for(var i = 0, ilen = array.length; i < ilen; i++) { | |
total = Math.abs(array[i]) | |
} | |
return total | |
} | |
function KickDetector(options) { | |
options = options || {} | |
this.timeWindow = options.timeWindow || 100 | |
this.kickCount = 0 | |
this.initLast() | |
} | |
var fn = KickDetector.prototype | |
fn.getArray = function() { return [] } | |
fn.update = function(dt) { | |
this.array = this.getArray() | |
var array = this.array | |
, total = addAll(array) * 100 | |
if (total < 1) { | |
this.initLast() | |
return | |
} | |
if (!this.lastTotal) { | |
this.lastTotal = total | |
return | |
} | |
this.isUp = total > this.lastTotal | |
if (!this.isUp && this.wasUp) { | |
this.kicked = true | |
} | |
this.wasUp = this.isUp | |
this.lastTotal = total | |
} | |
fn.initLast = function() { | |
this.wasUp = true // init | |
this.lastTotal = 1 | |
} | |
fn.draw = function() { | |
if (this.kicked && !this.windowOpen) { | |
this.windowOpen = true | |
this.kickCount += 1 | |
console.log('kick') | |
setTimeout(function() { | |
this.windowOpen = false | |
this.kicked = false | |
}.bind(this), this.timeWindow) | |
} | |
} |
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
window.requestAnimationFrame = (function(){ | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oCancelAnimationFrame || | |
window.msCancelAnimationFrame || | |
function( callback ){ | |
window.setTimeout(callback, 1000 / 60); | |
} | |
}()) | |
window.cancelAnimationFrame = (function(){ | |
return window.cancelAnimationFrame || | |
window.webkitCancelAnimationFrame || | |
window.mozCancelAnimationFrame || | |
window.oCancelAnimationFrame || | |
window.msCancelAnimationFrame || | |
window.clearTimeout | |
}) | |
function MainLoop(opts) { | |
this.spirits = [] | |
} | |
MainLoop.prototype = { | |
constructor: MainLoop.prototype.constructor | |
, start: function() { | |
this.lasttime = Date.now() | |
var step = (function () { | |
this.tick() | |
this.timer = requestAnimationFrame(step) | |
}).bind(this) | |
this.timer = requestAnimationFrame(step) | |
} | |
, stop: function() { | |
cancelAnimationFrame(this.timer) | |
this.timer = null | |
} | |
, isRunning: function() { | |
return !!this.timer | |
} | |
, preUpdate: function() {} | |
, preDraw: function() {} | |
, tick: function() { | |
var now = Date.now() | |
, dt = (now - this.lasttime) | |
if (dt < 5) { return } | |
dt /= 1000 | |
this.lasttime = now | |
this.preUpdate(dt) | |
this.preDraw() | |
this.spirits.forEach(function(spirit, i) { | |
spirit.update(dt) | |
spirit.draw() | |
}) | |
} | |
, addSpirit: function(spirit) { | |
var origDestroy = spirit.destroy | |
, spirits = this.spirits | |
spirit.destroy = function() { | |
var index = spirits.indexOf(spirit) | |
if (index > -1) { | |
spirits.splice(index, 1); | |
} | |
origDestroy.apply(this, arguments) | |
} | |
spirits.push(spirit) | |
} | |
, resetSpirit: function() { | |
this.spirits = [] | |
} | |
} |
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
window.AudioContext = window.AudioContext | |
|| window.mozAudioContext | |
|| window.webkitAudioContext | |
|| window.msAudioContext | |
|| window.oAudioContext | |
navigator.getUserMedia = navigator.getUserMedia | |
|| navigator.mozGetUserMedia | |
|| navigator.webkitGetUserMedia | |
|| navigator.msGetUserMedia | |
|| navigator.oGetUserMedia | |
function Microphone(options) { | |
options = options || {} | |
var audioContext = this.audioContext = new AudioContext() | |
var bufferSize = this.bufferSize = options.bufferSize || 2048 | |
this.processors = [] | |
if (options.analyse) { | |
this.defaultAnalyser = this.addAnalyser() | |
this.freqs = new Uint8Array(this.defaultAnalyser.frequencyBinCount) | |
this.times = new Uint8Array(this.defaultAnalyser.frequencyBinCount) | |
} | |
if (options.process) { | |
this.defaultProcessor = this.addProcessor() | |
} | |
} | |
var fn = Microphone.prototype | |
fn.filterNoise = function() { | |
// Simple noise filter. | |
var lp = this.lp = this.audioContext.createBiquadFilter() | |
lp.type = lp.LOWPASS | |
lp.frequency = 8000 | |
lp.Q = 0.1 | |
var hp = this.hp = this.audioContext.createBiquadFilter() | |
hp.type = hp.HIGHPASS | |
hp.frequency = 20 | |
hp.Q = 0.1 | |
} | |
fn.capture = function() { | |
this.filterNoise() | |
navigator.getUserMedia({ | |
audio: true | |
}, success.bind(this), error.bind(this)) | |
function success(stream) { | |
this.stream = stream | |
var src = this.audioContext.createMediaStreamSource(stream) | |
, node = src | |
if (this.lp) { | |
node.connect(this.lp) | |
node = this.lp | |
} | |
if (this.hp) { | |
node.connect(this.hp) | |
node = this.hp | |
} | |
node.connect(this.audioContext.destination) | |
this.processors.forEach(function(processor) { | |
processor(node) | |
}.bind(this)) | |
} | |
function error(e) { | |
throw new Error(e) | |
} | |
} | |
fn.getFreqs = function() { | |
this.defaultAnalyser.getByteFrequencyData(this.freqs) | |
return this.freqs | |
} | |
fn.getTimes = function() { | |
this.defaultAnalyser.getByteTimeDomainData(this.times) | |
return this.times | |
} | |
fn.addProcessor = function() { | |
var processor = this.audioContext.createScriptProcessor(this.bufferSize, 1, 1) | |
processor.connect(this.audioContext.destination) | |
this.processors.push(function(source, stream) { | |
source.connect(processor) | |
}) | |
return processor | |
} | |
fn.addAnalyser = function() { | |
var analyser = this.audioContext.createAnalyser() | |
analyser.connect(this.audioContext.destination) | |
analyser.smoothingTimeConstant = 0.8 | |
analyser.fftSize = this.bufferSize | |
analyser.minDecibels = -140 | |
analyser.maxDecibels = 0 | |
this.processors.push(function(source, stream) { | |
source.connect(analyser) | |
}) | |
return analyser | |
} |
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
function Virtualizer(options) { | |
options = options || {} | |
var height = this.height = options.height || 512 | |
var width = this.width = options.widget || 1024 | |
var canvas = document.querySelector('canvas') | |
canvas.height = height | |
canvas.width = width | |
this.ctx = canvas.getContext('2d') | |
} | |
var fn = Virtualizer.prototype | |
fn.getArray = function() { return [] } | |
fn.update = function(dt) { | |
this.array = this.getArray() | |
} | |
fn.draw = function() { | |
this.clearCanvas() | |
var array = this.array | |
var length = array.length | |
var value, percent, offset, barWidth | |
for(var i = 0, ilen = length; i < length; i++) { | |
value = array[i] | |
percent = value / 256 | |
height = this.height * percent | |
offset = this.height - height - 1 | |
barWidth = this.width / length | |
this.ctx.fillStyle = '#999' | |
this.ctx.fillRect(i * barWidth, offset, barWidth, height) | |
} | |
} | |
fn.clearCanvas = function() { | |
this.ctx.clearRect(0, 0, this.width, this.height) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment