bit crusher
by mohayonao
HTML
<script src="http://mohayonao.github.io/neume.js/build/neume.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/0.10.6/vue.min.js"></script>
<div id="app">
<button id="start" v-on="click:start">start</button>
<input type="range" min="1" max="16" v-model="bits"/> {{ bits}}
</div>
<canvas id="canvas"></canvas>
CSS
canvas { width:100%; height:240px; }
JavaScript
var Neume = neume(new AudioContext());
var synth = null;
function makeBitCurve(bits) {
var n = 1 << bits;
var curve = new Float32Array(65536);
for (var i = 0; i < curve.length; i++) {
var x = i / curve.length;
x = Math.floor(x * n) / n;
curve[i] = x * 2 - 1;
}
return curve;
}
var Synth = new Neume(function($, curve) {
var out;
out = $("sin", { freq: 440, mul: 1 });
out = $("shaper", { curve: curve }, out);
return out;
});
function draw(curve) {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 256;
context.fillStyle = "#fff";
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
for (var i = 0; i < curve.length; i++) {
var x = i / curve.length * canvas.width;
var y = curve[i] * canvas.height * -0.5 + canvas.height * 0.5;
context.lineTo(x, y);
}
context.stroke();
}
new Vue({
el: "#app",
data: {
bits: 7
},
methods: {
start: function() {
if (synth) {
synth.fadeOut("+0", 0.15);
synth = null;
} else {
var curve = makeBitCurve(this.bits);
draw(curve);
synth = new Synth(curve).fadeIn("+0", 0.15);
}
}
}
});