added audio generating script

This commit is contained in:
Sasserisop 2023-12-06 22:48:05 -07:00
parent 450da746bc
commit 77a42600b2
4 changed files with 419 additions and 2 deletions

View File

@ -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.

View File

@ -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>

View File

@ -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);
}

190
static/playaudio.js Normal file
View File

@ -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);
}