var frequencyInput = document.querySelector("input[frequency]");
var orderInput = document.querySelector("input[order]");
var waveformInput = document.getElementById("waveform").elements["waveform"];
var canvas = document.querySelector("canvas");
var context = canvas.getContext("2d");
var PI2 = Math.PI * 2.0;
var Scale = 64.0;
var time = 0.0;
var startTime = new Date().getTime();
var values = [];
var valuePointer = 0;
var x = 128.0,
y = 128.0;
function fourier(order) {
var phase = order * time * PI2;
var radius = 4.0 / (order * Math.PI) * Scale;
context.beginPath();
context.lineWidth = 1.0;
context.strokeStyle = "rgba(255,128,32,1.0)";
context.arc(x, y, radius, 0, PI2);
context.stroke();
context.strokeStyle = "rgba(255,255,255,0.4)";
context.moveTo(x, y);
x += Math.cos(phase) * radius;
y += Math.sin(phase) * radius;
context.lineTo(x, y);
context.stroke();
};
function connect() {
context.beginPath();
context.moveTo(x + 0.5, y + 0.5);
context.lineTo(256 + 0.5, y + 0.5);
context.strokeStyle = "rgba(255,255,32,1.0)";
context.stroke();
};
function drawWave() {
values[valuePointer++ & 255] = y;
context.beginPath();
context.strokeStyle = "rgba(0,255,0,1)";
context.moveTo(256 + 0.5, y + 0.5);
for (var i = 1; i < 256; ++i) {
context.lineTo(256 + i + 0.5, values[(valuePointer - i) & 255] + 0.5);
}
context.stroke();
}
(function frame() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
x = 144.0;
y = 128.0;
switch (waveformInput.value) {
case "square":
for (var order = 0; order <= orderInput.value; order++) {
fourier((order << 1) + 1);
}
break;
case "sawtooth":
for (var order = 1; order <= orderInput.value; order++) {
fourier(order << 1);
}
break;
}
connect();
drawWave();
var now = new Date().getTime();
time += (now - startTime) * Math.pow(10.0, frequencyInput.value);
startTime = now;
window.requestAnimationFrame(frame);
})();
!