Last active
May 27, 2016 12:17
-
-
Save dolpen/550ef9fa1b68e81c8bc5999d0eb0590c 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> | |
<html lang="ja"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title></title> | |
</head> | |
<body> | |
<div id="app"> | |
</div> | |
<script src="app.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
// サウンド再生デモ | |
(function (d, w) { | |
var config = { | |
svg: { | |
ns: 'http://www.w3.org/2000/svg' | |
}, | |
data: { | |
tick: 16, | |
fullSize: 128, | |
useSize: 64 | |
}, | |
view: { | |
barHeadHeight: 5, | |
outerWidth: 512, | |
outerHeight: 192, | |
innerWidth: 512, | |
innerHeight: 192 | |
} | |
}; | |
var utils = { | |
createSVGElement: function (name) { | |
return d.createElementNS(config.svg.ns, name); | |
}, | |
hsl: function (v) { | |
return 'hsl(' + v * 360 + ', 100%, 50%)'; | |
}, | |
hsla: function (v, a) { | |
return 'hsla(' + v * 360 + ', 100%, 50%, ' + a + ')'; | |
} | |
}; | |
var Loader = function () { | |
}; | |
Loader.prototype = { | |
load: function (u, f) { | |
var req = new XMLHttpRequest(); | |
req.responseType = 'arraybuffer'; | |
req.onreadystatechange = function () { | |
if (req.readyState === 4) { | |
if (req.status === 0 || req.status === 200) { | |
f(req.response); | |
} | |
} | |
}; | |
req.open('GET', u, true); | |
req.send(''); | |
} | |
}; | |
var Audio = function () { | |
var _context = w.AudioContext || w.webkitAudioContext; | |
this.context = new _context(); | |
this.analyser = this._initAnalyser(this.context); | |
this.source = null; | |
}; | |
Audio.prototype = { | |
_initAnalyser: function (_context) { | |
var analyser = _context.createAnalyser(); | |
analyser.fftSize = config.data.fullSize; | |
return analyser; | |
}, | |
_initOscillator: function (_context) { | |
var oscillator = _context.createOscillator(); | |
// method polyfill | |
oscillator.start = oscillator.start || oscillator.noteOn; | |
oscillator.stop = oscillator.stop || oscillator.noteOff; | |
return oscillator; | |
}, | |
setArrayBuffer: function (arrayBuffer) { | |
if (this.source !== null)return this; | |
var source = this.context.createBufferSource(); | |
this.context.decodeAudioData(arrayBuffer, function (buffer) { | |
source.buffer = buffer; | |
}); | |
this.source = source; | |
return this; | |
}, | |
connect: function () { | |
if (this.source === null)return this; | |
this.source.connect(this.analyser); | |
this.analyser.connect(this.context.destination); | |
return this; | |
}, | |
start: function (n) { | |
this.source.start(n); | |
}, | |
stop: function (n) { | |
this.source.start(n); | |
}, | |
getFFTData: function () { | |
var freqs = new Uint8Array(this.analyser.fftSize); | |
this.analyser.getByteFrequencyData(freqs); | |
return freqs; | |
} | |
}; | |
var LevelBar = function (k, w, parent) { | |
this.position = k; | |
this.width = w; | |
this.level = 0; | |
this.alpha = 1; | |
this.line = null; | |
this.parent = parent; | |
this._init(); | |
}; | |
LevelBar.prototype = { | |
_init: function () { | |
var rect = utils.createSVGElement('rect'); | |
rect.setAttributeNS(null, 'x', this.position * this.width); | |
rect.setAttributeNS(null, 'y', config.view.innerHeight); | |
rect.setAttributeNS(null, 'width', this.width); | |
rect.setAttributeNS(null, 'height', 0); | |
rect.setAttributeNS(null, 'fill', '#000000'); | |
this.parent.appendChild(rect); | |
this.line = rect; | |
}, | |
_updateLevel: function (level) { | |
var height = Math.max((level * config.view.innerHeight / 255) - config.view.barHeadHeight,0); | |
this.alpha *= 0.96; | |
if (this.level < level)this.alpha = 1.0; | |
this.line.setAttributeNS(null, 'y', (config.view.innerHeight - height)); | |
this.line.setAttributeNS(null, 'height', height); | |
this.line.setAttributeNS(null, 'fill', utils.hsla(1 - level / 255, this.alpha*0.4)); | |
this.level = level; | |
} | |
}; | |
var UpperLine = function (k, w, parent) { | |
this.position = k; | |
this.width = w; | |
this.level = 0; | |
this.alpha = 1; | |
this.line = null; | |
this.parent = parent; | |
this._init(); | |
}; | |
UpperLine.prototype = { | |
_init: function () { | |
var rect = utils.createSVGElement('rect'); | |
rect.setAttributeNS(null, 'x', this.position * this.width); | |
rect.setAttributeNS(null, 'y', config.view.innerHeight); | |
rect.setAttributeNS(null, 'width', this.width); | |
rect.setAttributeNS(null, 'height', 0); | |
rect.setAttributeNS(null, 'fill', '#000000'); | |
this.parent.appendChild(rect); | |
this.line = rect; | |
}, | |
_updateLevel: function (level) { | |
var pos = (level * config.view.innerHeight / 255); | |
var height = level > 0 ? config.view.barHeadHeight : 0; | |
this.alpha *= 0.96; | |
this.level *= 0.999; | |
if (this.level < level) { | |
this.alpha = 1.0; | |
this.level = level; | |
} | |
this.line.setAttributeNS(null, 'y', (config.view.innerHeight - pos)); | |
this.line.setAttributeNS(null, 'height', height); | |
this.line.setAttributeNS(null, 'fill', utils.hsla(1 - level / 255, this.alpha)); | |
this.level = level; | |
} | |
}; | |
var AnalyzerView = function () { | |
this.root = null; | |
this.lines = null; | |
this._init(); | |
}; | |
AnalyzerView.prototype = { | |
_init: function () { | |
var rectWigth = config.view.innerWidth / config.data.useSize; | |
var root = utils.createSVGElement('svg'); | |
root.setAttributeNS(null, 'width', config.view.outerWidth); | |
root.setAttributeNS(null, 'height', config.view.outerHeight); | |
root.setAttributeNS(null, 'viewBox', "0 0 " + config.view.innerWidth + " " + config.view.innerHeight); | |
root.style.background = '#000000'; | |
var lines = []; | |
var uppers = []; | |
for (var i = 0; i < config.data.useSize; i++) { | |
lines.push(new LevelBar(i, rectWigth, root)); | |
uppers.push(new UpperLine(i, rectWigth, root)); | |
} | |
this.lines = lines; | |
this.uppers = uppers; | |
this.root = root; | |
}, | |
_updateLevels: function (data) { | |
var lines = this.lines; | |
var uppers = this.uppers; | |
for (var i = 0; i < config.data.useSize; i++) { | |
lines[i]._updateLevel(data[i]); | |
uppers[i]._updateLevel(data[i]); | |
} | |
} | |
}; | |
var Player = function () { | |
this.audio = new Audio(); | |
this.analyzerView = new AnalyzerView(); | |
}; | |
Player.prototype = { | |
init: function (el) { | |
el.appendChild(this.analyzerView.root); | |
}, | |
tick: function () { | |
this.analyzerView._updateLevels(this.audio.getFFTData()); | |
} | |
}; | |
var bootstrap = function () { | |
var player = new Player(); | |
player.init(d.getElementById('app')); | |
var tick = function () { | |
player.tick(); | |
setTimeout(tick, config.data.tick); | |
}; | |
(new Loader()).load('', function (resp) { | |
player.audio.setArrayBuffer(resp).connect().start(0); | |
setTimeout(tick, config.data.tick); | |
}); | |
w.player = player; | |
}; | |
if (d.readyState !== "loading") { | |
bootstrap(); | |
} else { | |
d.addEventListener("DOMContentLoaded", bootstrap); | |
} | |
})(document, window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment