Skip to content

Instantly share code, notes, and snippets.

@jacksonhenry3
Created August 6, 2012 15:14
Show Gist options
  • Save jacksonhenry3/3275332 to your computer and use it in GitHub Desktop.
Save jacksonhenry3/3275332 to your computer and use it in GitHub Desktop.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type"
content="text/html; charset=ISO-8859-1">
<title>Fourier Transform in JavaScript</title>
<meta name="keywords"
content="graph, graphs, graphing, JavaScript, DHTML, Clymer, function, functions, Fourier, Fourier transform, FFT">
<style type="text/css" media="screen"></style>
</head>
<body>
<div id="gbox"
style="border: 1px solid black; position: absolute; top: 10px; left: 10px; width: 514px; height: 202px; background-color: rgb(255, 255, 187);">
<font size="-2">&nbsp;Function to be transformed</font></div>
<div id="fbox"
style="border: 1px solid black; position: absolute; top: 220px; left: 10px; width: 514px; height: 202px; background-color: rgb(255, 255, 187);">
<font size="-2">&nbsp;Fourier Transform</font></div>
<div id="formbox"
style="background-color: rgb(255, 255, 255); position: absolute; top: 10px; left: 530px; width: 270px; height: 541px; visibility: visible;">
<form method="get" name="f">
<p>Function<br>
<input name="func" value="sin(8*x)" size="40" tabindex="1" type="text"
border="0"></p>
<p><input name="xmin" value="0.0" size="10" tabindex="2" type="text"
border="0"> <label>x min</label><br>
<input name="xmax" value="+6.283" size="10" tabindex="3" type="text"
border="0"> <label>x max</label><br>
<input name="ymin" value="-1.5" size="10" tabindex="4" type="text"
border="0"> <label> y min</label><br>
<input name="ymax" value="+1.5" size="10" tabindex="5" type="text"
border="0"> <label>y max</label></p>
<p>&nbsp;&nbsp;&nbsp;<input name="replotbutton" value=" Replot! "
tabindex="6" onclick="replot()" type="button" border="0"></p>
<p><br>
</p>
<p>&nbsp;&nbsp;&nbsp;<input name="fftButton" value=" FFT! "
tabindex="7" onclick="fft()" type="button" border="0"></p>
<p><input name="numax" readonly="readonly" size="10" tabindex="12"
type="text" border="0"> <label>&#957; max</label><br>
<input name="omega" readonly="readonly" size="10" tabindex="13"
type="text" border="0"> <label>&#969; max</label></p>
<p><input name="Fmax" size="10" tabindex="8" type="text" border="0"> <label>F
max</label></p>
<p>&nbsp;&nbsp;&nbsp;<input name="replot2but" value=" Replot! "
tabindex="9" onclick="replot2()" type="button" border="0"></p>
<p><textarea name="exportfield" rows="20" cols="38"
readonly="readonly" tabindex="11" wrap="off"></textarea></p>
</form>
</div>
<script type="text/javascript">
var screenx=512, screeny=200, offset=10, x;
var yr = new Array(512); yi = new Array(512);
var n=1024, g=10, p=2*Math.PI/n, g1, l, m, k, k1, k2, k3;
var y1, y2, j;
var dend = "px; position:absolute; top:1px; width:2px; height:2px; font-size=1; background-color:#0000ff\'></div>"
var fend = "px; position:absolute; top:1px; width:1px; height:2px; font-size=1; background-color:#0000ff\'></div>"
for (var i=1; i<=screenx; i++) {
x=i + offset;
document.write("<div id=\'d"+i+"\' style=\' left:"+x+dend);
document.write("<div id=\'f"+i+"\' style=\' left:"+x+fend);
}
replot();
fft();
function replot() {
var xmin=1 * document.f.xmin.value;
var xmax=1 * document.f.xmax.value;
var ymin=1 * document.f.ymin.value;
var ymax=1 * document.f.ymax.value;
if (ymin==ymax) { ymin=-Math.abs(ymin); ymax=Math.abs(ymax);
document.f.ymin.value = ymin;
document.f.ymax.value = ymax; }
if (xmin==xmax) { xmin=-Math.abs(xmin); xmax=Math.abs(xmax);
document.f.xmin.value = xmin;
document.f.xmax.value = xmax; }
var func=document.f.func.value;
var xf=(xmax-xmin)/screenx, yf=screeny/(ymax-ymin);
var y, x1, y1, obj, ptr;
var scry = screeny + offset;
with (Math) {
for (var i=1; i<=screenx; i++) {
x = i*xf + xmin;
y =eval(func);
if (y>ymax) y=ymax;
if (y<ymin) y=ymin;
y1=scry-(y-ymin)*yf;
ptr = "d"+i;
obj = document.getElementById(ptr);
obj.style.top = y1;
} } }
function fft() {
var func=document.f.func.value;
var xmin=1 * document.f.xmin.value;
var xmax=1 * document.f.xmax.value;
var xf=(xmax-xmin)/n, mg1;
with (Math) {
for (var i=1; i<=n; i++) {
x = i*xf + xmin;
y =eval(func);
yr[i]=y; yi[i]=0;
} }
with (Math) {
for (l=0; l<=(g-1); l++) {
g1 = pow(2,(g-l-1));
m=0;
for (i=1; i<=pow(2,l); i++) {
k1=floor(m/g1);
kaylyn();
y1=cos(p*k2);
y2=-sin(p*k2);
for (j=1; j<=g1; j++) {
m=m+1;
mg1=m+g1;
y3=yr[mg1]*y1-yi[mg1]*y2;
y4=yr[mg1]*y2+yi[mg1]*y1;
yr[mg1]=yr[m]-y3;
yi[mg1]=yi[m]-y4;
yr[m]=yr[m]+y3;
yi[m]=yi[m]+y4;
}
m = m + g1;
} }
for (i=0; i<=(n-1); i++) {
k1 = i;
kaylyn();
if (k2>=i) continue;
k3 = yr[i+1];
yr[i+1] = yr[k2+1];
yr[k2+1] = k3;
k3 = yi[i+1];
yi[i+1] = yi[k2+1];
yi[k2+1] = k3;
}
var ymax=0;
for (i=1; i<=n/2; i++) {
yr[i] = Math.sqrt((yr[i]*yr[i] + yi[i]*yi[i]))*2/n;
ymax=max(yr[i], ymax);
}
yr[1] = yr[1]/2;
var ymaxstr = Math.ceil(ymax*1.1*100)/100;
document.f.Fmax.value = ymaxstr.toString();
replot2();
export1();
} }
function kaylyn() {
k2=0;
for (k=1; k<=g; k++) {
k3=Math.floor(k1/2);
k2=2*(k2-k3) + k1;
k1=k3;
}
}
function replot2() {
var xmin = 1 * document.f.xmin.value;
var xmax = 1 * document.f.xmax.value;
var ymin=0;
var ymax=1 * document.f.Fmax.value;
var numax = n/2/(xmax-xmin);
var omega = numax*2*Math.PI;
var numaxstr = Math.round(numax*10)/10;
document.f.numax.value = numaxstr.toString();
var omegastr = Math.round(omega*10)/10;
document.f.omega.value = omegastr.toString();
var yf=screeny/(ymax-ymin);
var y, x1, y1, obj, ptr;
var yoff = 220+screeny;
with (Math) {
for (var i=1; i<=n/2; i++) {
y = yr[i];
if (y>ymax) y=ymax;
if (y<ymin) y=ymin;
y1=round(yoff-(y-ymin)*yf);
ptr="f"+i;
obj=document.getElementById(ptr);
obj.style.top=y1;
obj.style.height=yoff-y1+1;
} } }
function export1() {
var longstr="";
for (var i=1; i<=n/2; i++) {
longstr += i-1 + ", " + yr[i] + "\n";
}
document.f.exportfield.value = longstr;
}
</script>
<div id="layer1"
style="border: 0px solid black; position: absolute; top: 440px; left: 10px; width: 514px; height: 202px; background-color: rgb(255, 255, 255);">
<p>This page demonstrates the use of JavaScript to perform Fourier
Transforms, and DHTML to produce graphs of functions. Enter a function
in terms of x in the top box. Enter minimum and maximum values for x
and y in the next four boxes. Then, hit the Replot! button. If you make
a mistake in entering a formula, use the Refresh feature of your
browser.</p>
<p>Functions available in JavaScript are abs(x), acos(x), asin(x),
atan(x), ceil(x), cos(x), exp(x), floor(x), log(x), max(x,n), min(x,n),
pow(x,n), random(), round(x), sin(x), sqrt(x) and tan(x).</p>
<p>Once a function is displayed, a Fourier Transform can be performed
by pressing the FFT! button. Although only 512 points are shown in the
upper grapph, a Fast Fourier Transform is calculated on 1024 points
from the entered function. So the Nyquist frequency for the FT is twice
the apparent Nyquist frequency for the upper plot. Each of the
resulting 512 real and imaginary FT points are squared and added
together to produce a power spectrum. The maximum frequency, &#957;, and
angular freqency, &#969; (=2&#960;&#957;), are displayed as determined
from the maximum and mininum x values. The individual data points of
the power spectrum are also listed in the lower text box. The vertical
axis of the Fourier transform can be magnified by changing the value of
Fmax and hitting the lower Replot! button.</p>
<p>Here's a good <a
href="http://www.cage.curtin.edu.au/mechanical/info/vibrations/tut4.htm">tutorial
on
Fourier
transforms</a>.</p>
And one from <a href="http://www.colby.edu/chemistry/NMR/NMR.html">Colby
College</a>.
<p>Here are some interesting functions on which to perform Fourier
transforms:</p>
<ul>
<li><i>sine wave</i>: sin(128*x) </li>
<li><i>two sine waves</i>: sin(100*x)+2*sin(150*x) </li>
<li><i>modulated sine wave</i>: sin(140*x)*sin(20*x) </li>
<li><i>modulated sine wave</i>: sin(100*x)*sin(120*x) </li>
<li><i>sine wave exponentially damped</i>: sin(128*x)*exp(-2*x) </li>
<li><i>square wave</i>: (sin(32*x)&gt;0)?1:-1 </li>
<li><i>sine wave pulse</i>: (x&lt;0.2)?sin(128*x):0 </li>
<li><i>sine of x-squared</i>: sin(4*x*x) </li>
<li><i>sine wave log multiplied</i>: sin(100*x)*log(x) </li>
<li><i>sinc function</i>: sin(100*x)/(100*x) </li>
<li><i>sine of an exponential</i>: sin(exp(x)) </li>
<li><i>sine squared</i>: sin(x)*sin(x)-0.5</li>
<li><span style="font-style: italic;">multiple pulse</span>:
sin(200*x)*(exp(-20*(x-1)*(x-1))+exp(-20*(x-3)*(x-3))+exp(-20*(x-5)*(x-5)))</li>
</ul>
<p>For the following use, a whole number, such as 8, for x max.</p>
<ul>
<li><i>square pulse</i>: (x&lt;0.1)?1:0 </li>
<li><i>sawtooth</i>: 2*x%1-0.5 </li>
<li><i>triangle</i>: (8*x%2&lt;1)?8*x%1-0.5:0.5-(8*x%1) </li>
<li><i>gaussian</i>: exp(-(x-4)*(x-4)*1000) </li>
</ul>
<hr>
<p><font size="-1"><a href="http://home.cincyarts.org">Other pages</a>
by the author. <a href="mailto:jclymer@fuse.net">Email</a>.<br>
</font><font size="-1">Debut: December 26, 2003. Revision No. 7. <csobj
format="LongDate" h="16" region="0" t="DateTime" w="169">August 23,
2006</csobj>
</font>Visitors:<!-- Start of StatCounter Code -->
<script type="text/javascript" language="javascript">
var sc_project=497377;
var sc_partition=3;
</script>
<script type="text/javascript" language="javascript"
src="http://www.statcounter.com/counter/counter.js"></script><noscript><a
href="http://www.statcounter.com/"
target="_blank"><img
src="http://c4.statcounter.com/counter.php?sc_project=497377&java=0"
alt="free hit counter script" border="0"></a> </noscript><!-- End of StatCounter Code --></p>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment