From ab232005066b0b6de14bd71a37d920ff09bd2f8f Mon Sep 17 00:00:00 2001 From: hle0 <91701075+hle0@users.noreply.github.com> Date: Tue, 7 Jun 2022 18:05:45 -0400 Subject: [PATCH] add support for picking audio files and playing them back! --- css/master.css | 7 +++++ index.html | 1 + js/fft/FFTdata.js | 30 +++++++++++++++---- js/interface/mouseControl.js | 58 +++++++++++++++++++++++++++++++++++- js/main.js | 2 +- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/css/master.css b/css/master.css index 5276ce1..c808c4b 100755 --- a/css/master.css +++ b/css/master.css @@ -9,3 +9,10 @@ body { margin: 0; overflow: hidden; } + +#filePicker { + position: absolute; + bottom: 0; + right: 0; + z-index: 1; +} \ No newline at end of file diff --git a/index.html b/index.html index 952d34a..9cb61ae 100755 --- a/index.html +++ b/index.html @@ -34,6 +34,7 @@
+ diff --git a/js/fft/FFTdata.js b/js/fft/FFTdata.js index 3858f91..a9a5694 100755 --- a/js/fft/FFTdata.js +++ b/js/fft/FFTdata.js @@ -6,18 +6,25 @@ class _spectrogram { this.analyser = false; } init(stream) { - this.audioCtx = new AudioContext(); - this.analyser = this.audioCtx.createAnalyser(); - this.analyser.fftSize = 2048*4; - this.tmpStream = this.audioCtx.createMediaStreamSource(stream); - this.audioCtx.createMediaStreamSource(stream).connect(this.analyser); - this.analyser.smoothingTimeConstant = 0; + this.resetAnalyser(stream); this.data = new Uint8Array(this.analyser.frequencyBinCount); this.analyserFrequencyBinCount = this.analyser.frequencyBinCount; this.analyserSampleRate = this.audioCtx.sampleRate; } + resetAnalyser(stream) { + if (this.audioCtx) this.audioCtx.close(); + this.audioCtx = new AudioContext(); + this.resetContext(); + this.audioCtx.createMediaStreamSource(stream).connect(this.analyser); + this.tmpStream = this.audioCtx.createMediaStreamSource(stream); + } + resetContext() { + this.analyser = this.audioCtx.createAnalyser(); + this.analyser.fftSize = 2048*4; + this.analyser.smoothingTimeConstant = 0; + } update() { this.analyser.getByteFrequencyData(this.data); // @@ -27,4 +34,15 @@ class _spectrogram { // transform(this.data, this.empty); // console.log(this.empty); } + changeStream(stream) { + this.audioCtx.close(); + this.audioCtx = null; + this.resetAnalyser(stream); + } + swapContext(ctx) { + let ret = this.audioCtx; + this.audioCtx = ctx; + this.resetContext(); + return ret; + } } diff --git a/js/interface/mouseControl.js b/js/interface/mouseControl.js index d6a4af0..aa14758 100755 --- a/js/interface/mouseControl.js +++ b/js/interface/mouseControl.js @@ -1,5 +1,6 @@ +let _audio = null; let mClick = { x : 0, @@ -38,6 +39,9 @@ class _buttonControl { if (child) {return child.spectrogramPauseToggle()} this.spectrogram.setPause(this.spectrogram.paused ? false : true); this.fft.setPause(this.fft.paused ? false : true); + if (_audio) { + this.spectrogram.paused ? _audio.pause() : _audio.play(); + } if (this.spectrogram.paused) {buttonList.buttons[5].setText(`‖`);} else {buttonList.buttons[5].setText(`▶`);} @@ -85,6 +89,43 @@ class _buttonControl { rolloffSave.push({ ...smoothPeaks[i] }); } } + changeUserDevice(child=false) { + if (child) {return child.changeUserDevice()} + navigator.mediaDevices.getUserMedia({ audio: true }).then(a => { + console.log('changing to ' + a.toString()); + fft.changeStream(a); + }).catch(console.error); + } + playSoundFile(child=false) { + if (child) {return child.playSoundFile()} + let fs = document.querySelector("#filePicker").files; + if (fs.length < 1) { + alert("Please pick a file first!"); + return; + } + let f = fs[0]; + let u = URL.createObjectURL(f); + let a = new Audio(u); + let o; + + _audio = a; + + a.addEventListener('ended', ev => { + _audio = null; + URL.revokeObjectURL(u); + this.changeUserDevice(); + }); + + let c = new AudioContext(); + let source = c.createMediaElementSource(a); + source.connect(c.destination); + + o = fft.swapContext(c); + + source.connect(fft.analyser); + + a.play(); + } } let buttonControl = new _buttonControl(); @@ -166,7 +207,22 @@ function buttonsInit() { tmpButton.setPos(20,140); tmpButton.setText(`save rolloff`); buttonList.add(tmpButton); - + // changeUserDevice + tmpButton = new _button(); + tmpButton.childBind(buttonControl); + tmpButton.setFunction(buttonControl.changeUserDevice) + tmpButton.setSize(140, 20); + tmpButton.setPos(20,170); + tmpButton.setText(`select user device`); + buttonList.add(tmpButton); + // playSoundFile + tmpButton = new _button(); + tmpButton.childBind(buttonControl); + tmpButton.setFunction(buttonControl.playSoundFile) + tmpButton.setSize(140, 20); + tmpButton.setPos(20,200); + tmpButton.setText(`play sound`); + buttonList.add(tmpButton); // // tmpButton = new _button(); // tmpButton.childBind(buttonControl); diff --git a/js/main.js b/js/main.js index e81b0fd..078c3ed 100755 --- a/js/main.js +++ b/js/main.js @@ -129,7 +129,7 @@ function spectrum(stream) { } // ============================== controls ============================== - if ((m.x < 300 && m.y < 200)) { + if ((m.x < 300 && m.y < 240)) { showControls = true; alertPitchInput.style.visibility = "visible"; }