Skip to content

Instantly share code, notes, and snippets.

@dolpen
Last active May 27, 2016 12:17
Show Gist options
  • Save dolpen/550ef9fa1b68e81c8bc5999d0eb0590c to your computer and use it in GitHub Desktop.
Save dolpen/550ef9fa1b68e81c8bc5999d0eb0590c to your computer and use it in GitHub Desktop.
<!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>
// サウンド再生デモ
(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