Skip to content

Instantly share code, notes, and snippets.

@nrempel
Created June 23, 2015 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nrempel/397ed6a405bae4b0d503 to your computer and use it in GitHub Desktop.
Save nrempel/397ed6a405bae4b0d503 to your computer and use it in GitHub Desktop.
Fourier series
<div>
<h3>Fourier series</h3>
<canvas width="512" height="256"></canvas>
<div>
<span>Frequency</span>
<input frequency type="range" min="-5" max="-3" value="-3.5" step="0.0001">
</div>
<div>
<span>Order</span>
<input order type="range" min="0" max="16" value="4" step="1">
</div>
<div>
<span>Waveform</span>
<form id="waveform">
<label>Square
<input type="radio" name="waveform" value="square" checked>
</label>
<label>Sawtooth
<input type="radio" name="waveform" value="sawtooth">
</label>
</form>
</div>
</div>
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);
})();
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-family: Open Sans;
font-size: 12px;
color: orange;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
display: -webkit-flex;
-webkit-align-items: center;
-webkit-justify-content: center;
background: #222;
}
h3 {
margin: 0 0 3px 1px;
}
canvas {
background: black;
}
span {
width: 80px;
margin: 0;
padding: 0;
display: inline-block;
}
form, label {
display: inline-block;
}
input[type="range"] {
margin: 0;
padding: 0;
width: 432px;
display: inline;
vertical-align: middle;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment