貧乏リバーブ
by mohayonao
HTML
<script src="http://mohayonao.github.io/neume.js/build/neume.min.js"></script>
<button id="start">start</button>
<canvas id="canvas"></canvas>
CSS
canvas { width:100% }
JavaScript
var decayTime = 6;
var Neume = neume(new AudioContext());
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 512;
context.lineWidth = 0.05;
context.strokeStyle = "#2c3e50";
context.fillStyle = "#fff";
function decayToCoef(t) {
return Math.exp(Math.log(0.001) / (t * 44100));
}
function makeReverbBuffer(data, spec) {
var amp = 1;
for (var i = 0; i < data.length; i++) {
data[i] = Math.random() * 2 - 1;
data[i] *= amp;
data[i] *= i < spec.room ? 1 : 0.05;
amp *= spec.coef;
}
return data;
}
function draw(data) {
context.fillRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(0, canvas.height * 0.5);
for (var i = 0; i < data.length; i++) {
var x = (i / data.length) * canvas.width;
var y = canvas.height * 0.5 - (canvas.height) * data[i] * 0.5;
context.lineTo(x, y);
}
context.stroke();
}
var reverb = new Float32Array(44100 * 4);
makeReverbBuffer(reverb, { coef: decayToCoef(decayTime), room: 128 });
draw(reverb);
var Synth = new Neume(function($) {
var out;
out = $("sin", { freq: 1760 });
out = $("xline", { dur: 0.5 }, out).on("end", function(e) {
this.stop(e.playbackTime);
});
return $("out", { bus: 1 }, out);
});
var Efx = new Neume(function($, reverb) {
var out;
out = $("in", 1);
out = $("conv", { buf: reverb }, out);
return out;
});
var synth = null;
var timer = null;
$("#start").on("click", function() {
if (synth) {
synth.fadeOut("+0", 0.5);
synth = null;
timer.stop();
$(this).css("color", "black");
} else {
synth = new Efx(Neume.Buffer.from(reverb)).start();
timer = new Neume.Interval(1, function() {
new Synth().start();
}).start();
$(this).css("color", "red");
}
});