added audio generating script
This commit is contained in:
parent
450da746bc
commit
77a42600b2
|
@ -48,7 +48,7 @@ then $f, g$ are orthogonal
|
|||
the Fourier expansion is called an ortho normal expansion, Taylor is not orthonormal.
|
||||
#end of lec 28
|
||||
#start of lec 29
|
||||
Last lecture we derived how to find the coefficients in a Fourier series.
|
||||
Last lecture we derived how to find the coefficients of a Fourier series.
|
||||
$f(x)=\frac{a_{0}}{2}+\sum_{n=1}^\infty\left( a_{n}\cos\left( \frac{n\pi x}{L} \right) + b_{n}\sin\left( \frac{n\pi x}{L}\right) \right)$
|
||||
$x \in [-L,L]$
|
||||
### 1st convergence theorem:
|
||||
|
@ -174,4 +174,41 @@ then:
|
|||
$$\bar{f}(x)=\frac{2}{\pi}+\frac{2}{\pi}\sum_{k=1}^\infty\left( \frac{1}{2k+1}-\frac{1}{2k-1} \right)\cos(2k\pi x)$$
|
||||
Even with 10 terms, we get a pretty good approximation:
|
||||
![fouriercosineofsin.png](drawings/fouriercosineofsin.png)
|
||||
Here's a little script I wrote to generate an audible waveform of this Fourier series!
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<button id="playButton">Play the sound</button>
|
||||
|
||||
<canvas id='scope'></canvas>
|
||||
|
||||
<canvas id='spectrum'></canvas>
|
||||
|
||||
<div class="slidecontainer">
|
||||
<p>Number of harmonics: <span id="textHarmonics"></span></p>
|
||||
<input type="range" min="0" max="100" value="50" style="width: 70%;" id="sliderHarmonics">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="slidecontainer">
|
||||
<p>Frequency: <span id="textFreq"></span></p>
|
||||
<input type="range" min="0" max="440" value="220" style="width: 70%;" id="sliderFreq">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script src="playaudio.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
We have prepared ourselves now, now we start solving PDE's. He's encouraging us to attend the lectures in these last two weeks. He's making it sound like PDE's are hard.
|
|
@ -74,7 +74,7 @@ but we have a boundary condition:
|
|||
$X(0)=0=c_{1}+c_{2}$
|
||||
$c_{1}+c_{2}=0$
|
||||
$X(L)=c_{1}e^{\sqrt{ -\lambda }L}+c_{2}e^{-\sqrt{ -\lambda }L}=0$
|
||||
this has a unique solution, as the determinant is non-zero: $\det\left(\begin{matrix}1 & 1 \\e^{\sqrt{ -\lambda }L} & e^{-\sqrt{ -\lambda }L}\end{matrix}\right)=e^{-\sqrt{ -\lambda }L}-e^{\sqrt{ -\lambda }L}\ne 0$ (as long as $L\ne 0$, which is true since we are assuming the tube has non-zero length.)
|
||||
this has a unique solution, as the determinant is non-zero: $\det\left(\begin{matrix}1 & 1 \\e^{\sqrt{ -\lambda }L} & e^{-\sqrt{ -\lambda }L}\end{matrix}\right)=e^{-\sqrt{ -\lambda }L}-e^{\sqrt{ -\lambda }L}\ne 0$ (as long as $L\ne 0$, which is true since we are assuming the tube has non-zero length. Remember $\lambda\ne 0$ either since $\lambda<0$ in this case.)
|
||||
the only solution is $c_{1}=0,\ c_{2}=0$
|
||||
which gives $X(x)=0$ for all $x\in[0,L]$ very boring solution!
|
||||
</br>
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
var slider = document.getElementById("sliderHarmonics");
|
||||
var textHarmonics = document.getElementById("textHarmonics");
|
||||
var sliderFreq = document.getElementById("sliderFreq")
|
||||
var textFreq = document.getElementById("textFreq");
|
||||
var playing = document.getElementById("playButton");
|
||||
textHarmonics.innerHTML = slider.value; // Display the default slider value
|
||||
textFreq.innerHTML=sliderFreq.value
|
||||
|
||||
var isPlaying = false;
|
||||
var real = new Float32Array(110);
|
||||
var imag = new Float32Array(110);
|
||||
|
||||
var cspec = document.getElementById('spectrum'),
|
||||
ctxspec = cspec.getContext("2d");
|
||||
|
||||
cspec.height = 200;
|
||||
cspec.width = 500;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sliderFreq.oninput = function() {
|
||||
textFreq.innerHTML=this.value;
|
||||
osc.frequency.value=this.value;
|
||||
}
|
||||
// Update the current slider value (each time you drag the slider handle)
|
||||
slider.oninput = function() {
|
||||
textHarmonics.innerHTML = this.value;
|
||||
if (isPlaying){
|
||||
var numCoeffs = this.value; // The more coefficients you use, the better the approximation
|
||||
//var real = new Float32Array(numCoeffs+10);
|
||||
//var imag = new Float32Array(numCoeffs+10);
|
||||
|
||||
//real[0] = 0.5;
|
||||
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
||||
// imag[i] = 1 / (i * Math.PI);
|
||||
//}
|
||||
for (var i = 1; i <= 110; i++) {
|
||||
real[i]=0;
|
||||
}
|
||||
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
||||
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
||||
}
|
||||
|
||||
osc.frequency.value = textFreq.innerHTML;
|
||||
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
||||
//var real = new Float32Array(imag.length); // cos
|
||||
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
||||
osc.setPeriodicWave(customWave);
|
||||
|
||||
|
||||
|
||||
//isPlaying = false;
|
||||
// osc.stop();
|
||||
//playSound(this.value);}
|
||||
}}
|
||||
|
||||
|
||||
//setup audio context
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
var context = new window.AudioContext();
|
||||
|
||||
//create nodes
|
||||
var osc; //create in event listener so we can press the button more than once
|
||||
var masterGain = context.createGain();
|
||||
var analyser = context.createAnalyser();
|
||||
|
||||
//routing
|
||||
masterGain.connect(analyser);
|
||||
analyser.connect(context.destination);
|
||||
|
||||
|
||||
|
||||
//draw function for canvas
|
||||
function drawWave(analyser, ctx) {
|
||||
|
||||
var buffer = new Float32Array(1024),
|
||||
w = ctx.canvas.width;
|
||||
|
||||
ctx.strokeStyle = "#D44"; //reddish color
|
||||
ctx.setTransform(1,0,0,-1,0,100.5); // flip y-axis and translate to center
|
||||
ctx.lineWidth = 2;
|
||||
ctxspec.strokeStyle = "#44D" //blueish color
|
||||
ctxspec.setTransform(1,0,0,1,0,100.5);
|
||||
ctxspec.lineWidth = 2;
|
||||
var wspec=ctxspec.canvas.width;
|
||||
(function loop() {
|
||||
analyser.getFloatTimeDomainData(buffer);
|
||||
var prevValue=999;
|
||||
var currentValue=999;
|
||||
for (var i=10; i<1024; i++){
|
||||
currentValue=buffer[i];
|
||||
if (currentValue>prevValue && currentValue>-0.05 && currentValue<0.05){
|
||||
break;
|
||||
}
|
||||
prevValue=currentValue;
|
||||
}
|
||||
ctx.clearRect(0, -100, w, ctx.canvas.height);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, buffer[i] * 90);
|
||||
for (var x = i; x < w+i; x += 2) ctx.lineTo(x-i+2, buffer[x] * 90);
|
||||
ctx.stroke();
|
||||
|
||||
//spectrum stuff:
|
||||
//real=getReal();
|
||||
//console.log(real);
|
||||
ctxspec.clearRect(0, -100, wspec, ctxspec.canvas.height);
|
||||
ctxspec.beginPath();
|
||||
ctxspec.moveTo(0, 80);
|
||||
for (var j=0; j<100; j++){
|
||||
ctxspec.lineTo(j*10,real[j]*400+80);
|
||||
}
|
||||
ctxspec.stroke();
|
||||
if (isPlaying) requestAnimationFrame(loop)
|
||||
})();
|
||||
}
|
||||
|
||||
//button trigger
|
||||
$(function() {
|
||||
var c = document.getElementById('scope'),
|
||||
ctx = c.getContext("2d");
|
||||
|
||||
c.height = 200;
|
||||
c.width = 600;
|
||||
|
||||
// make 0-line permanent as background
|
||||
ctx.moveTo(0, 100.5);
|
||||
ctx.lineTo(c.width, 100.5);
|
||||
ctx.stroke();
|
||||
c.style.backgroundImage = "url(" + c.toDataURL() + ")";
|
||||
|
||||
$('button').on('mousedown', function() {
|
||||
|
||||
if (playing.innerHTML==="Pause sound"){
|
||||
playing.innerHTML="Play the sound";
|
||||
isPlaying = false;
|
||||
osc.stop();
|
||||
}else{
|
||||
playing.innerHTML="Pause sound";
|
||||
playSound(textHarmonics.innerHTML);
|
||||
}});
|
||||
});
|
||||
|
||||
function playSound(h){
|
||||
var c = document.getElementById('scope'),
|
||||
ctx = c.getContext("2d");
|
||||
osc = context.createOscillator();
|
||||
//osc settings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var numCoeffs = h; // The more coefficients you use, the better the approximation
|
||||
|
||||
|
||||
//real[0] = 0.5;
|
||||
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
||||
// imag[i] = 1 / (i * Math.PI);
|
||||
//}
|
||||
for (var i = 1; i <= 110; i++) {
|
||||
real[i]=0;
|
||||
}
|
||||
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
||||
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
||||
//var real = new Float32Array(imag.length); // cos
|
||||
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
||||
osc.setPeriodicWave(customWave);
|
||||
osc.frequency.value = textFreq.innerHTML;
|
||||
osc.connect(masterGain);
|
||||
osc.start();
|
||||
isPlaying = true;
|
||||
|
||||
drawWave(analyser, ctx);
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
var slider = document.getElementById("sliderHarmonics");
|
||||
var textHarmonics = document.getElementById("textHarmonics");
|
||||
var sliderFreq = document.getElementById("sliderFreq")
|
||||
var textFreq = document.getElementById("textFreq");
|
||||
var playing = document.getElementById("playButton");
|
||||
textHarmonics.innerHTML = slider.value; // Display the default slider value
|
||||
textFreq.innerHTML=sliderFreq.value
|
||||
|
||||
var isPlaying = false;
|
||||
var real = new Float32Array(110);
|
||||
var imag = new Float32Array(110);
|
||||
|
||||
var cspec = document.getElementById('spectrum'),
|
||||
ctxspec = cspec.getContext("2d");
|
||||
|
||||
cspec.height = 200;
|
||||
cspec.width = 500;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sliderFreq.oninput = function() {
|
||||
textFreq.innerHTML=this.value;
|
||||
osc.frequency.value=this.value;
|
||||
}
|
||||
// Update the current slider value (each time you drag the slider handle)
|
||||
slider.oninput = function() {
|
||||
textHarmonics.innerHTML = this.value;
|
||||
if (isPlaying){
|
||||
var numCoeffs = this.value; // The more coefficients you use, the better the approximation
|
||||
//var real = new Float32Array(numCoeffs+10);
|
||||
//var imag = new Float32Array(numCoeffs+10);
|
||||
|
||||
//real[0] = 0.5;
|
||||
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
||||
// imag[i] = 1 / (i * Math.PI);
|
||||
//}
|
||||
for (var i = 1; i <= 110; i++) {
|
||||
real[i]=0;
|
||||
}
|
||||
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
||||
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
||||
}
|
||||
|
||||
osc.frequency.value = textFreq.innerHTML;
|
||||
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
||||
//var real = new Float32Array(imag.length); // cos
|
||||
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
||||
osc.setPeriodicWave(customWave);
|
||||
|
||||
|
||||
|
||||
//isPlaying = false;
|
||||
// osc.stop();
|
||||
//playSound(this.value);}
|
||||
}}
|
||||
|
||||
|
||||
//setup audio context
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
var context = new window.AudioContext();
|
||||
|
||||
//create nodes
|
||||
var osc; //create in event listener so we can press the button more than once
|
||||
var masterGain = context.createGain();
|
||||
var analyser = context.createAnalyser();
|
||||
|
||||
//routing
|
||||
masterGain.connect(analyser);
|
||||
analyser.connect(context.destination);
|
||||
|
||||
|
||||
|
||||
//draw function for canvas
|
||||
function drawWave(analyser, ctx) {
|
||||
|
||||
var buffer = new Float32Array(1024),
|
||||
w = ctx.canvas.width;
|
||||
|
||||
ctx.strokeStyle = "#D44"; //reddish color
|
||||
ctx.setTransform(1,0,0,-1,0,100.5); // flip y-axis and translate to center
|
||||
ctx.lineWidth = 2;
|
||||
ctxspec.strokeStyle = "#44D" //blueish color
|
||||
ctxspec.setTransform(1,0,0,1,0,100.5);
|
||||
ctxspec.lineWidth = 2;
|
||||
var wspec=ctxspec.canvas.width;
|
||||
(function loop() {
|
||||
analyser.getFloatTimeDomainData(buffer);
|
||||
var prevValue=999;
|
||||
var currentValue=999;
|
||||
for (var i=10; i<1024; i++){
|
||||
currentValue=buffer[i];
|
||||
if (currentValue>prevValue && currentValue>-0.05 && currentValue<0.05){
|
||||
break;
|
||||
}
|
||||
prevValue=currentValue;
|
||||
}
|
||||
ctx.clearRect(0, -100, w, ctx.canvas.height);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, buffer[i] * 90);
|
||||
for (var x = i; x < w+i; x += 2) ctx.lineTo(x-i+2, buffer[x] * 90);
|
||||
ctx.stroke();
|
||||
|
||||
//spectrum stuff:
|
||||
//real=getReal();
|
||||
//console.log(real);
|
||||
ctxspec.clearRect(0, -100, wspec, ctxspec.canvas.height);
|
||||
ctxspec.beginPath();
|
||||
ctxspec.moveTo(0, 80);
|
||||
for (var j=0; j<100; j++){
|
||||
ctxspec.lineTo(j*10,real[j]*400+80);
|
||||
}
|
||||
ctxspec.stroke();
|
||||
if (isPlaying) requestAnimationFrame(loop)
|
||||
})();
|
||||
}
|
||||
|
||||
//button trigger
|
||||
$(function() {
|
||||
var c = document.getElementById('scope'),
|
||||
ctx = c.getContext("2d");
|
||||
|
||||
c.height = 200;
|
||||
c.width = 600;
|
||||
|
||||
// make 0-line permanent as background
|
||||
ctx.moveTo(0, 100.5);
|
||||
ctx.lineTo(c.width, 100.5);
|
||||
ctx.stroke();
|
||||
c.style.backgroundImage = "url(" + c.toDataURL() + ")";
|
||||
|
||||
$('button').on('mousedown', function() {
|
||||
|
||||
if (playing.innerHTML==="Pause sound"){
|
||||
playing.innerHTML="Play the sound";
|
||||
isPlaying = false;
|
||||
osc.stop();
|
||||
}else{
|
||||
playing.innerHTML="Pause sound";
|
||||
playSound(textHarmonics.innerHTML);
|
||||
}});
|
||||
});
|
||||
|
||||
function playSound(h){
|
||||
var c = document.getElementById('scope'),
|
||||
ctx = c.getContext("2d");
|
||||
osc = context.createOscillator();
|
||||
//osc settings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var numCoeffs = h; // The more coefficients you use, the better the approximation
|
||||
|
||||
|
||||
//real[0] = 0.5;
|
||||
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
||||
// imag[i] = 1 / (i * Math.PI);
|
||||
//}
|
||||
for (var i = 1; i <= 110; i++) {
|
||||
real[i]=0;
|
||||
}
|
||||
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
||||
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
||||
//var real = new Float32Array(imag.length); // cos
|
||||
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
||||
osc.setPeriodicWave(customWave);
|
||||
osc.frequency.value = textFreq.innerHTML;
|
||||
osc.connect(masterGain);
|
||||
osc.start();
|
||||
isPlaying = true;
|
||||
|
||||
drawWave(analyser, ctx);
|
||||
}
|
Loading…
Reference in New Issue