From 77a42600b270edc66598eb35d4c5b30befeb26a7 Mon Sep 17 00:00:00 2001 From: Sasserisop Date: Wed, 6 Dec 2023 22:48:05 -0700 Subject: [PATCH] added audio generating script --- content/Fourier Series (lec 28-29).md | 39 +++- ...bles & Eigen value problems (lec 26-28).md | 2 +- content/scripts/playaudio.js | 190 ++++++++++++++++++ static/playaudio.js | 190 ++++++++++++++++++ 4 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 content/scripts/playaudio.js create mode 100644 static/playaudio.js diff --git a/content/Fourier Series (lec 28-29).md b/content/Fourier Series (lec 28-29).md index 5556766..528d1a5 100644 --- a/content/Fourier Series (lec 28-29).md +++ b/content/Fourier Series (lec 28-29).md @@ -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! + + + + + + + + + +  + +  + +  + +
+

Number of harmonics:

+ +
+ +

Frequency:

+ + + +
+ + + + + + + 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. \ No newline at end of file diff --git a/content/Separation of variables & Eigen value problems (lec 26-28).md b/content/Separation of variables & Eigen value problems (lec 26-28).md index 9e2fa01..4a22628 100644 --- a/content/Separation of variables & Eigen value problems (lec 26-28).md +++ b/content/Separation of variables & Eigen value problems (lec 26-28).md @@ -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!
diff --git a/content/scripts/playaudio.js b/content/scripts/playaudio.js new file mode 100644 index 0000000..823a123 --- /dev/null +++ b/content/scripts/playaudio.js @@ -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); + } \ No newline at end of file diff --git a/static/playaudio.js b/static/playaudio.js new file mode 100644 index 0000000..823a123 --- /dev/null +++ b/static/playaudio.js @@ -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); + } \ No newline at end of file