From 49474d0b848195702eaaac1457358cf680d92008 Mon Sep 17 00:00:00 2001 From: tommy martinez Date: Tue, 2 Aug 2022 00:23:40 -0400 Subject: [PATCH 1/5] worklet sound engine functioning --- public/worklet/spc.js | 19 +++++++++++++++ public/worklet/squarify.js | 37 +++++++++++++++++++++++++++++ src/Player.js | 48 +++++++++++++++++++++++++++++--------- src/main.js | 48 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 public/worklet/spc.js create mode 100644 public/worklet/squarify.js create mode 100644 src/main.js diff --git a/public/worklet/spc.js b/public/worklet/spc.js new file mode 100644 index 0000000..7609250 --- /dev/null +++ b/public/worklet/spc.js @@ -0,0 +1,19 @@ +console.log("hello"); +class SpectralFilter extends AudioWorkletProcessor { + // When constructor() undefined, the default constructor will be + // implicitly used. + + process(inputs, outputs) { + // By default, the node has single input and output. + const input = inputs[0]; + const output = outputs[0]; + + for (let channel = 0; channel < output.length; ++channel) { + output[channel].set(input[channel]); + } + + return true; + } +} + +registerProcessor('spectralfilter', SpectralFilter); diff --git a/public/worklet/squarify.js b/public/worklet/squarify.js new file mode 100644 index 0000000..b69dea6 --- /dev/null +++ b/public/worklet/squarify.js @@ -0,0 +1,37 @@ +console.log("hello"); +class SpectralFilter extends AudioWorkletProcessor { + // Custom AudioParams can be defined with this static getter. + static get parameterDescriptors() { + return [{ name: 'gain', defaultValue: 1., minValue:0, maxValue:1. }]; + } + + constructor() { + // The super constructor call is required. + super(); + //hann window + const hann = 0., 0.000602, 0.002408, 0.005412, 0.009607, 0.014984, 0.02153, 0.029228, 0.03806, 0.048005, 0.059039, 0.071136, 0.084265, 0.098396, 0.113495, 0.129524, 0.146447, 0.164221, 0.182803, 0.20215, 0.222215, 0.242949, 0.264302, 0.286222, 0.308658, 0.331555, 0.354858, 0.37851, 0.402455, 0.426635, 0.450991, 0.475466, 0.5, 0.524534, 0.549009, 0.573365, 0.597545, 0.62149, 0.645142, 0.668445, 0.691342, 0.713778, 0.735698, 0.757051, 0.777785, 0.79785, 0.817197, 0.835779, 0.853553, 0.870476, 0.886505, 0.901604, 0.915735, 0.928864, 0.940961, 0.951995, 0.96194, 0.970772, 0.97847, 0.985016, 0.990393, 0.994588, 0.997592, 0.999398, 1., 0.999398, 0.997592, 0.994588, 0.990393, 0.985016, 0.97847, 0.970772, 0.96194, 0.951995, 0.940961, 0.928864, 0.915735, 0.901604, 0.886505, 0.870476, 0.853553, 0.835779, 0.817197, 0.79785, 0.777785, 0.757051, 0.735698, 0.713778, 0.691342, 0.668445, 0.645142, 0.62149, 0.597545, 0.573365, 0.549009, 0.524534, 0.5, 0.475466, 0.450991, 0.426635, 0.402455, 0.37851, 0.354858, 0.331555, 0.308658, 0.286222, 0.264302, 0.242949, 0.222215, 0.20215, 0.182803, 0.164221, 0.146447, 0.129524, 0.113495, 0.098396, 0.084265, 0.071136, 0.059039, 0.048005, 0.03806, 0.029228, 0.02153, 0.014984, 0.009607, 0.005412, 0.002408, 0.000602; + } + + process(inputs, outputs, parameters) { + const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); + const input = inputs[0]; + const output = outputs[0]; + const gain = parameters.gain; + for (let channel = 0; channel < input.length; ++channel) { + const inputChannel = input[channel]; + const outputChannel = output[channel]; + if (gain.length === 1) { + for (let i = 0; i < inputChannel.length; ++i) + //"squarify" the sin tone + outputChannel[i] = clampNumber(inputChannel[i], -.5, .5) * gain[0]; + } else { + for (let i = 0; i < inputChannel.length; ++i) + outputChannel[i] = inputChannel[i] * gain[i]; + } + } + + return true; + } +} + +registerProcessor('spectralfilter', SpectralFilter); diff --git a/src/Player.js b/src/Player.js index bd581fb..d2b4473 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,22 +1,48 @@ import React from 'react'; - class Player extends React.Component { + + audio() { - /*let maxi; - initAudioEngine().then((dspEngine)=>{ - maxi = dspEngine; - setup(); - //Get audio code from script element - maxi.setAudioCode("myAudioScript"); - - }) - */ + async function processSomeStuff(){ + let context = new AudioContext(); + const oscillator = new OscillatorNode(context); + oscillator.frequency.value = 450; + oscillator.frequency.amplitude = .1; + await context.audioWorklet.addModule('worklet/spc.js') + console.log('i did it'); + const spectralNode = new window.AudioWorkletNode(context, 'spectralfilter'); + oscillator.connect(spectralNode).connect(context.destination); + oscillator.start(); + //let filterParam = spectralNode.parameters.get('filter') + //const player = new Tone.Player("./sounds/overhere.wav").connect(spectralNode); + //spectralNode.connect(context.destination); + //player.loop = true; + //player.start(); + + + /* + //oscillator.connect(spectralNode).connect(context.destination); + //spectralNode.connect(context.destination); + //oscillator.start(); + */ + + //let windowsize = spectralNode.parameters.get('windowsize'); + + //let hopsize = spectralNode.parameters.get('hopsize'); + //let overlaper = spectralNode.parameters.get('overlaps'); + //let gain = spectralNode.parameters.get('gain'); + //console.log(gain); + return oscillator; + } + processSomeStuff(); } + render() { return ( -
+
+
); diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..2dd32c0 --- /dev/null +++ b/src/main.js @@ -0,0 +1,48 @@ +let filterParam = {}; +let context = {}; + +function updateFilter(slidey){ + filterParam.setValueAtTime(slidey, context.currentTime); + console.log(slidey); +} + +async function processSomeStuff(){ + context = new AudioContext(); + + const audio = new Audio("./sounds/overhere.wav"); + /* + const oscillator = new OscillatorNode(context); + oscillator.frequency.value = 450; + oscillator.frequency.amplitude = .1; + */ + //await context.audioWorklet.addModule('js/complex.js') + await context.audioWorklet.addModule('js/spectralfilter.js') + + const spectralNode = new AudioWorkletNode(context, 'spectralfilter'); + const source = context.createMediaElementSource(audio); + source.connect(spectralNode).connect(context.destination); + audio.loop = true; + audio.play(); + filterParam = spectralNode.parameters.get('filter') + + + //const player = new Tone.Player("./sounds/overhere.wav").connect(spectralNode); + //spectralNode.connect(context.destination); + //player.loop = true; + //player.start(); + + + /* + //oscillator.connect(spectralNode).connect(context.destination); + //spectralNode.connect(context.destination); + //oscillator.start(); + */ + + //let windowsize = spectralNode.parameters.get('windowsize'); + + //let hopsize = spectralNode.parameters.get('hopsize'); + //let overlaper = spectralNode.parameters.get('overlaps'); + //let gain = spectralNode.parameters.get('gain'); + //console.log(gain); + +} From 71c29fcf3753f962639afa77959be9b707954177 Mon Sep 17 00:00:00 2001 From: tommy martinez Date: Tue, 2 Aug 2022 02:10:49 -0400 Subject: [PATCH 2/5] fft library imported into worklets --- package.json | 1 + public/index.html | 3 +- public/worklet/fft.js | 162 +++++++++++++++++++++++++++++++++ public/worklet/spc.js | 177 ++++++++++++++++++++++++++++++++++++- public/worklet/squarify.js | 8 +- src/Player.js | 38 +++----- yarn.lock | 5 ++ 7 files changed, 363 insertions(+), 31 deletions(-) create mode 100644 public/worklet/fft.js diff --git a/package.json b/package.json index 3085e7d..673dadb 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "react-dom": "^18.2.0", "react-script-tag": "^1.1.2", "react-scripts": "5.0.1", + "signalsmith-js-fft": "^1.0.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/public/index.html b/public/index.html index fa5ba29..c629cde 100644 --- a/public/index.html +++ b/public/index.html @@ -24,7 +24,8 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + Sound-Chain + diff --git a/public/worklet/fft.js b/public/worklet/fft.js new file mode 100644 index 0000000..19da330 --- /dev/null +++ b/public/worklet/fft.js @@ -0,0 +1,162 @@ +// A fairly small and neat FFT - not the fastest, but not terrible +// Expects interleaved complex pairs (i.e. `[real0, imag0, real1, imag1, ...]`) +function FFT(size) { + if (!(this instanceof FFT)) return new FFT(size); + + var twiddleRealCache = new Float64Array(size); + var twiddleImagCache = new Float64Array(size); + var stride = 1; + while (stride < size) { + for (var i = 0; i < stride; ++i) { + var twiddleReal = Math.cos(Math.PI*i/stride); + var twiddleImag = -Math.sin(Math.PI*i/stride); + twiddleRealCache[stride + i] = twiddleReal; + twiddleImagCache[stride + i] = twiddleImag; + } + stride *= 2; + } + + function fftStep2(buffer, stride, direction) { + var offset = 0; + var doubleStride = stride*2; + while (offset < size*2) { + for (var i = 0; i < stride; ++i) { + var indexA = offset + i*2, indexB = indexA + doubleStride; + var realA = buffer[indexA], imagA = buffer[indexA + 1]; + var realB = buffer[indexB], imagB = buffer[indexB + 1]; + + var diffReal = realA - realB; + var diffImag = imagA - imagB; + var twiddleReal = twiddleRealCache[stride + i]; + var twiddleImag = direction*twiddleImagCache[stride + i]; + + buffer[indexA] = realA + realB; + buffer[indexA + 1] = imagA + imagB; + buffer[indexB] = diffReal*twiddleReal - diffImag*twiddleImag; + buffer[indexB + 1] = diffReal*twiddleImag + diffImag*twiddleReal; + } + offset += doubleStride*2; + } + } + function fft(buffer) { + for (var s = size/2; s >= 1; s /= 2) { + fftStep2(buffer, s, 1); + } + } + function ifft(buffer) { + for (var s = size/2; s >= 1; s /= 2) { + fftStep2(buffer, s, -1); + } + } + + function bitSwap(x, N) { + var result = 0; + N >>= 1; + while (N) { + result = (result << 1) + (x&1); + N >>= 1; + x >>= 1; + } + return result; + } + var permutations = []; + for (var i = 0; i < size; i++) { + var i2 = bitSwap(i, size); + if (i < i2) { + permutations.push(i); + permutations.push(i2); + } + } + function fft_permute(buffer, offset, step, N) { + for (var i = 0; i < permutations.length; i += 2) { + var index1 = permutations[i], index2 = permutations[i + 1]; + + var tmpReal = buffer[index1*2], tmpImag = buffer[index1*2 + 1]; + buffer[index1*2] = buffer[index2*2]; + buffer[index1*2 + 1] = buffer[index2*2 + 1]; + buffer[index2*2] = tmpReal; + buffer[index2*2 + 1] = tmpImag; + } + } + function getInPlace(input, output) { + if (!output) return input; + for (var i = 0; i < size*2; ++i) { + output[i] = input[i]; + } + return output; + } + this.fft = function(input, output) { + var buffer = getInPlace(input, output); + fft(buffer, 0, 2, size); + fft_permute(buffer, 0, 2, size); + }; + this.ifft = function(input, output) { + var buffer = getInPlace(input, output); + ifft(buffer, 0, 2, size); + fft_permute(buffer, 0, 2, size); + }; +} +// Real-valued FFT +// Accepts real waveforms, and interleaved complex spectra (with Nyquist stuffed into bin 0) +function RFFT(size) { + if (!(this instanceof RFFT)) return new RFFT(size); + var hSize = size>>1, qSize = size>>2; + var complexFft = new FFT(hSize); + + var complexBuffer = new Float64Array(size); + var twiddles = new Float64Array(hSize + 2); + for (var i = 0; i <= qSize; ++i) { + var rotPhase = -2*Math.PI*i/size; + twiddles[2*i] = Math.sin(rotPhase); + twiddles[2*i + 1] = -Math.cos(rotPhase); + } + + this.fft = function(input, output) { + complexFft.fft(input, complexBuffer); + output[0] = complexBuffer[0] + complexBuffer[1], + output[1] = complexBuffer[0] - complexBuffer[1]; + for (var i = 1; i <= qSize; ++i) { + var conjI = hSize - i; + + var oddR = (complexBuffer[2*i] + complexBuffer[2*conjI])*0.5; + var oddI = (complexBuffer[2*i + 1] - complexBuffer[2*conjI + 1])*0.5; + var iEvenR = (complexBuffer[2*i] - complexBuffer[2*conjI])*0.5; + var iEvenI = (complexBuffer[2*i + 1] + complexBuffer[2*conjI + 1])*0.5; + var twiddleR = twiddles[2*i], twiddleI = twiddles[2*i + 1]; + var rotR = iEvenR*twiddleR - iEvenI*twiddleI; + var rotI = iEvenR*twiddleI + iEvenI*twiddleR; + + output[2*i] = oddR + rotR; + output[2*i + 1] = oddI + rotI; + output[2*conjI] = oddR - rotR; + output[2*conjI + 1] = rotI - oddI; + } + }; + this.ifft = function(input, output) { + complexBuffer[0] = input[0] + input[1], + complexBuffer[1] = input[0] - input[1]; + for (var i = 1; i <= qSize; ++i) { + var conjI = hSize - i; + + var oddR = input[2*i] + input[2*conjI]; + var oddI = input[2*i + 1] - input[2*conjI + 1]; + var iEvenR = input[2*i] - input[2*conjI]; + var iEvenI = input[2*i + 1] + input[2*conjI + 1]; + var twiddleR = twiddles[2*i], twiddleI = twiddles[2*i + 1]; + var rotR = iEvenR*twiddleR + iEvenI*twiddleI; + var rotI = iEvenI*twiddleR - iEvenR*twiddleI; + + complexBuffer[2*i] = oddR + rotR; + complexBuffer[2*i + 1] = oddI + rotI; + complexBuffer[2*conjI] = oddR - rotR; + complexBuffer[2*conjI + 1] = rotI - oddI; + } + complexFft.ifft(complexBuffer, output); + }; +} +if (typeof module === 'object' && module) { + module.exports = { + FFT: FFT, + RFFT: RFFT + }; +} \ No newline at end of file diff --git a/public/worklet/spc.js b/public/worklet/spc.js index 7609250..5a48d22 100644 --- a/public/worklet/spc.js +++ b/public/worklet/spc.js @@ -1,7 +1,174 @@ -console.log("hello"); +// A fairly small and neat FFT - not the fastest, but not terrible +// Expects interleaved complex pairs (i.e. `[real0, imag0, real1, imag1, ...]`) +function FFT(size) { + if (!(this instanceof FFT)) return new FFT(size); + + var twiddleRealCache = new Float64Array(size); + var twiddleImagCache = new Float64Array(size); + var stride = 1; + while (stride < size) { + for (var i = 0; i < stride; ++i) { + var twiddleReal = Math.cos(Math.PI*i/stride); + var twiddleImag = -Math.sin(Math.PI*i/stride); + twiddleRealCache[stride + i] = twiddleReal; + twiddleImagCache[stride + i] = twiddleImag; + } + stride *= 2; + } + + function fftStep2(buffer, stride, direction) { + var offset = 0; + var doubleStride = stride*2; + while (offset < size*2) { + for (var i = 0; i < stride; ++i) { + var indexA = offset + i*2, indexB = indexA + doubleStride; + var realA = buffer[indexA], imagA = buffer[indexA + 1]; + var realB = buffer[indexB], imagB = buffer[indexB + 1]; + + var diffReal = realA - realB; + var diffImag = imagA - imagB; + var twiddleReal = twiddleRealCache[stride + i]; + var twiddleImag = direction*twiddleImagCache[stride + i]; + + buffer[indexA] = realA + realB; + buffer[indexA + 1] = imagA + imagB; + buffer[indexB] = diffReal*twiddleReal - diffImag*twiddleImag; + buffer[indexB + 1] = diffReal*twiddleImag + diffImag*twiddleReal; + } + offset += doubleStride*2; + } + } + function fft(buffer) { + for (var s = size/2; s >= 1; s /= 2) { + fftStep2(buffer, s, 1); + } + } + function ifft(buffer) { + for (var s = size/2; s >= 1; s /= 2) { + fftStep2(buffer, s, -1); + } + } + + function bitSwap(x, N) { + var result = 0; + N >>= 1; + while (N) { + result = (result << 1) + (x&1); + N >>= 1; + x >>= 1; + } + return result; + } + var permutations = []; + for (var i = 0; i < size; i++) { + var i2 = bitSwap(i, size); + if (i < i2) { + permutations.push(i); + permutations.push(i2); + } + } + function fft_permute(buffer, offset, step, N) { + for (var i = 0; i < permutations.length; i += 2) { + var index1 = permutations[i], index2 = permutations[i + 1]; + + var tmpReal = buffer[index1*2], tmpImag = buffer[index1*2 + 1]; + buffer[index1*2] = buffer[index2*2]; + buffer[index1*2 + 1] = buffer[index2*2 + 1]; + buffer[index2*2] = tmpReal; + buffer[index2*2 + 1] = tmpImag; + } + } + function getInPlace(input, output) { + if (!output) return input; + for (var i = 0; i < size*2; ++i) { + output[i] = input[i]; + } + return output; + } + this.fft = function(input, output) { + var buffer = getInPlace(input, output); + fft(buffer, 0, 2, size); + fft_permute(buffer, 0, 2, size); + }; + this.ifft = function(input, output) { + var buffer = getInPlace(input, output); + ifft(buffer, 0, 2, size); + fft_permute(buffer, 0, 2, size); + }; +} +// Real-valued FFT +// Accepts real waveforms, and interleaved complex spectra (with Nyquist stuffed into bin 0) +function RFFT(size) { + if (!(this instanceof RFFT)) return new RFFT(size); + var hSize = size>>1, qSize = size>>2; + var complexFft = new FFT(hSize); + + var complexBuffer = new Float64Array(size); + var twiddles = new Float64Array(hSize + 2); + for (var i = 0; i <= qSize; ++i) { + var rotPhase = -2*Math.PI*i/size; + twiddles[2*i] = Math.sin(rotPhase); + twiddles[2*i + 1] = -Math.cos(rotPhase); + } + + this.fft = function(input, output) { + complexFft.fft(input, complexBuffer); + output[0] = complexBuffer[0] + complexBuffer[1], + output[1] = complexBuffer[0] - complexBuffer[1]; + for (var i = 1; i <= qSize; ++i) { + var conjI = hSize - i; + + var oddR = (complexBuffer[2*i] + complexBuffer[2*conjI])*0.5; + var oddI = (complexBuffer[2*i + 1] - complexBuffer[2*conjI + 1])*0.5; + var iEvenR = (complexBuffer[2*i] - complexBuffer[2*conjI])*0.5; + var iEvenI = (complexBuffer[2*i + 1] + complexBuffer[2*conjI + 1])*0.5; + var twiddleR = twiddles[2*i], twiddleI = twiddles[2*i + 1]; + var rotR = iEvenR*twiddleR - iEvenI*twiddleI; + var rotI = iEvenR*twiddleI + iEvenI*twiddleR; + + output[2*i] = oddR + rotR; + output[2*i + 1] = oddI + rotI; + output[2*conjI] = oddR - rotR; + output[2*conjI + 1] = rotI - oddI; + } + }; + this.ifft = function(input, output) { + complexBuffer[0] = input[0] + input[1], + complexBuffer[1] = input[0] - input[1]; + for (var i = 1; i <= qSize; ++i) { + var conjI = hSize - i; + + var oddR = input[2*i] + input[2*conjI]; + var oddI = input[2*i + 1] - input[2*conjI + 1]; + var iEvenR = input[2*i] - input[2*conjI]; + var iEvenI = input[2*i + 1] + input[2*conjI + 1]; + var twiddleR = twiddles[2*i], twiddleI = twiddles[2*i + 1]; + var rotR = iEvenR*twiddleR + iEvenI*twiddleI; + var rotI = iEvenI*twiddleR - iEvenR*twiddleI; + + complexBuffer[2*i] = oddR + rotR; + complexBuffer[2*i + 1] = oddI + rotI; + complexBuffer[2*conjI] = oddR - rotR; + complexBuffer[2*conjI + 1] = rotI - oddI; + } + complexFft.ifft(complexBuffer, output); + }; +} +if (typeof module === 'object' && module) { + module.exports = { + FFT: FFT, + RFFT: RFFT + }; +} + +var fft = new FFT(256); // Complex FFT +var rfft = new RFFT(256); // Real FFT + +console.log(fft); class SpectralFilter extends AudioWorkletProcessor { // When constructor() undefined, the default constructor will be // implicitly used. + //let FFT = ssfft.FFT, RFFT = ssfft.RFFT; process(inputs, outputs) { // By default, the node has single input and output. @@ -9,7 +176,13 @@ class SpectralFilter extends AudioWorkletProcessor { const output = outputs[0]; for (let channel = 0; channel < output.length; ++channel) { - output[channel].set(input[channel]); + const inputChannel = input[channel]; + const outputChannel = output[channel]; + + for (let i = 0; i < inputChannel.length; ++i) { + outputChannel[i] = inputChannel[i] * .1; + } + } return true; diff --git a/public/worklet/squarify.js b/public/worklet/squarify.js index b69dea6..e5a4500 100644 --- a/public/worklet/squarify.js +++ b/public/worklet/squarify.js @@ -21,10 +21,12 @@ class SpectralFilter extends AudioWorkletProcessor { const inputChannel = input[channel]; const outputChannel = output[channel]; if (gain.length === 1) { - for (let i = 0; i < inputChannel.length; ++i) - //"squarify" the sin tone + for (let i = 0; i < inputChannel.length; ++i) { outputChannel[i] = clampNumber(inputChannel[i], -.5, .5) * gain[0]; - } else { + } + //"squarify" the sin tone + } + else { for (let i = 0; i < inputChannel.length; ++i) outputChannel[i] = inputChannel[i] * gain[i]; } diff --git a/src/Player.js b/src/Player.js index d2b4473..e570f3e 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,11 +1,19 @@ import React from 'react'; - +let ssfft = require('signalsmith-js-fft'); +let FFT = ssfft.FFT, RFFT = ssfft.RFFT; class Player extends React.Component { + constructor(props) { + super(props); + + //this.onMove = this.onMove.bind(this); + //this.testVarible= "this is a test"; + } + audio() { - async function processSomeStuff(){ - let context = new AudioContext(); + async function processSomeStuff() { + const context = new AudioContext(); const oscillator = new OscillatorNode(context); oscillator.frequency.value = 450; oscillator.frequency.amplitude = .1; @@ -14,26 +22,6 @@ class Player extends React.Component { const spectralNode = new window.AudioWorkletNode(context, 'spectralfilter'); oscillator.connect(spectralNode).connect(context.destination); oscillator.start(); - //let filterParam = spectralNode.parameters.get('filter') - //const player = new Tone.Player("./sounds/overhere.wav").connect(spectralNode); - //spectralNode.connect(context.destination); - //player.loop = true; - //player.start(); - - - /* - //oscillator.connect(spectralNode).connect(context.destination); - //spectralNode.connect(context.destination); - //oscillator.start(); - */ - - //let windowsize = spectralNode.parameters.get('windowsize'); - - //let hopsize = spectralNode.parameters.get('hopsize'); - //let overlaper = spectralNode.parameters.get('overlaps'); - //let gain = spectralNode.parameters.get('gain'); - //console.log(gain); - return oscillator; } processSomeStuff(); } @@ -41,8 +29,8 @@ class Player extends React.Component { render() { return ( -
- +
+
); diff --git a/yarn.lock b/yarn.lock index 95a0782..223995f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8222,6 +8222,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signalsmith-js-fft@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signalsmith-js-fft/-/signalsmith-js-fft-1.0.0.tgz#8798f8bf4ba37d5a7a857deb6bb45ec1a7ccc33f" + integrity sha512-BZYb8zvvlfF1rck0XDrZqA+Q8rpn3A5PO/CVpEO1YM29jCdMTjJGODGb/k/Pa98wQ9DxwCLg7SvThzorFJk7cg== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" From 05a8bd1393e76339fc8cc3f89e5d39af2708a418 Mon Sep 17 00:00:00 2001 From: tommy martinez Date: Wed, 3 Aug 2022 00:47:46 -0400 Subject: [PATCH 3/5] audio engine updates created some objects and variables for the spectral processing, made a random phase generator because we won't store phases on-chain created a mock "ah"-vowel sound NFT of my voice in max --- public/worklet/spc.js | 23 ++++++++++++++++++++--- src/App.js | 1 + src/Player.js | 2 -- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/public/worklet/spc.js b/public/worklet/spc.js index 5a48d22..2cb65c2 100644 --- a/public/worklet/spc.js +++ b/public/worklet/spc.js @@ -161,10 +161,27 @@ if (typeof module === 'object' && module) { }; } -var fft = new FFT(256); // Complex FFT -var rfft = new RFFT(256); // Real FFT +let fftSize = 512; + +var fft = new FFT(fftSize); // Complex FFT +//var rfft = new RFFT(512); // Real FFT + +//our spectral NFT +var vowelNFT = [0.255795, 2.180136, 3.209771, 2.731534, 1.820246, 1.495044, 3.272544, 2.310845, 5.144471, 2.91, 0.919624, 0.34142, 0.679509, 0.381155, 0.636831, 1.160013, 0.094173, 0.193721, 0.150465, 0.12147, 0.099303, 0.09309, 0.098961, 0.066721, 0.028414, 0.059244, 0.033274, 0.024482, 0.041223, 0.025929, 0.019325, 0.05797, 0.099241, 0.126397, 0.080319, 0.07242, 0.046754, 0.020103, 0.04397, 0.021902, 0.022018, 0.013881, 0.007026, 0.000497, 0.003684, 0.006626, 0.012554, 0.007694, 0.006612, 0.014619, 0.008457, 0.003559, 0.007018, 0.00406, 0.00762, 0.019043, 0.030558, 0.021751, 0.041281, 0.033161, 0.018786, 0.009123, 0.014886, 0.010089, 0.002634, 0.016033, 0.015593, 0.019621, 0.011461, 0.030579, 0.017091, 0.017846, 0.031331, 0.02156, 0.011481, 0.017571, 0.015572, 0.032011, 0.02798, 0.024011, 0.00675, 0.003581, 0.010511, 0.007497, 0.004385, 0.002594, 0.0028, 0.000956, 0.002014, 0.002165, 0.001523, 0.001887, 0.00179, 0.001908, 0.002222, 0.003154, 0.000279, 0.001348, 0.00312, 0.002663, 0.001165, 0.000662, 0.001085, 0.000368, 0.000632, 0.000674, 0.000168, 0.000505, 0.000188, 0.000244, 0.000747, 0.000747, 0.000208, 0.000918, 0.000907, 0.000504, 0.000223, 0.001154, 0.000298, 0.000362, 0.000793, 0.000194, 0.000145, 0.00024, 0.001135, 0.00091, 0.000892, 0.00055, 0.000101, 0.000349, 0.000395, 0.000585, 0.00098, 0.001045, 0.000869, 0.00015, 0.000951, 0.000662, 0.000631, 0.000604, 0.000709, 0.000598, 0.000639, 0.00044, 0.000288, 0.000666, 0.00051, 0.000763, 0.000776, 0.000945, 0.000946, 0.000732, 0.000788, 0.001809, 0.001703, 0.000402, 0.001103, 0.000869, 0.00093, 0.000495, 0.000223, 0.000933, 0.000788, 0.000873, 0.00055, 0.000232, 0.000492, 0.00036, 0.000139, 0.000524, 0.000137, 0.000379, 0.000324, 0.000394, 0.000778, 0.000363, 0.000532, 0.000457, 0.001099, 0.000502, 0.000299, 0.000376, 0.000364, 0.000449, 0.000818, 0.000292, 0.000711, 0.000157, 0.000971, 0.001605, 0.001201, 0.000134, 0.000377, 0.000835, 0.000477, 0.000548, 0.000753, 0.000416, 0.000659, 0.000564, 0.000275, 0.000143, 0.000058, 0.0006, 0.000223, 0.000082, 0.000117, 0.00047, 0.000364, 0.000407, 0.000347, 0.000363, 0.000337, 0.000275, 0.000178, 0.000329, 0.000248, 0.000212, 0.000138, 0.000322, 0.000306, 0.000242, 0.000213, 0.000925, 0.00076, 0.000455, 0.000911, 0.000256, 0.000321, 0.000378, 0.000436, 0.000245, 0.000477, 0.000164, 0.000123, 0.000095, 0.0001, 0.000098, 0.000099, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000097, 0.000097, 0.000097]; + + +//create random phase values +var rPhase = [fftSize]; +for (let i = 0; i < fftSize; i ++) { + rPhase[i] = (((Math.random()) * 2) - 1) * .1; + rPhase[i] = rPhase[i].toFixed(2); + //console.log(rPhase[i]); +} + +var spectrum = new Float64Array(fftSize * 2); +//we just need half of this... +console.log(spectrum.length); -console.log(fft); class SpectralFilter extends AudioWorkletProcessor { // When constructor() undefined, the default constructor will be // implicitly used. diff --git a/src/App.js b/src/App.js index c30d32f..2eb7061 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,5 @@ import logo from './logo.svg'; + {/*import './App.css';*/} function App() { diff --git a/src/Player.js b/src/Player.js index e570f3e..683e611 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,6 +1,4 @@ import React from 'react'; -let ssfft = require('signalsmith-js-fft'); -let FFT = ssfft.FFT, RFFT = ssfft.RFFT; class Player extends React.Component { constructor(props) { From 558697926c460bcdcaa76d5dd2e7dd61cee26170 Mon Sep 17 00:00:00 2001 From: tommy martinez Date: Thu, 4 Aug 2022 23:48:08 -0400 Subject: [PATCH 4/5] almost working audio engine need to implement windowing function and crosscheck frame/hop sizes --- public/worklet/spc.js | 97 ++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/public/worklet/spc.js b/public/worklet/spc.js index 2cb65c2..94e83ac 100644 --- a/public/worklet/spc.js +++ b/public/worklet/spc.js @@ -161,47 +161,84 @@ if (typeof module === 'object' && module) { }; } -let fftSize = 512; - -var fft = new FFT(fftSize); // Complex FFT -//var rfft = new RFFT(512); // Real FFT - -//our spectral NFT -var vowelNFT = [0.255795, 2.180136, 3.209771, 2.731534, 1.820246, 1.495044, 3.272544, 2.310845, 5.144471, 2.91, 0.919624, 0.34142, 0.679509, 0.381155, 0.636831, 1.160013, 0.094173, 0.193721, 0.150465, 0.12147, 0.099303, 0.09309, 0.098961, 0.066721, 0.028414, 0.059244, 0.033274, 0.024482, 0.041223, 0.025929, 0.019325, 0.05797, 0.099241, 0.126397, 0.080319, 0.07242, 0.046754, 0.020103, 0.04397, 0.021902, 0.022018, 0.013881, 0.007026, 0.000497, 0.003684, 0.006626, 0.012554, 0.007694, 0.006612, 0.014619, 0.008457, 0.003559, 0.007018, 0.00406, 0.00762, 0.019043, 0.030558, 0.021751, 0.041281, 0.033161, 0.018786, 0.009123, 0.014886, 0.010089, 0.002634, 0.016033, 0.015593, 0.019621, 0.011461, 0.030579, 0.017091, 0.017846, 0.031331, 0.02156, 0.011481, 0.017571, 0.015572, 0.032011, 0.02798, 0.024011, 0.00675, 0.003581, 0.010511, 0.007497, 0.004385, 0.002594, 0.0028, 0.000956, 0.002014, 0.002165, 0.001523, 0.001887, 0.00179, 0.001908, 0.002222, 0.003154, 0.000279, 0.001348, 0.00312, 0.002663, 0.001165, 0.000662, 0.001085, 0.000368, 0.000632, 0.000674, 0.000168, 0.000505, 0.000188, 0.000244, 0.000747, 0.000747, 0.000208, 0.000918, 0.000907, 0.000504, 0.000223, 0.001154, 0.000298, 0.000362, 0.000793, 0.000194, 0.000145, 0.00024, 0.001135, 0.00091, 0.000892, 0.00055, 0.000101, 0.000349, 0.000395, 0.000585, 0.00098, 0.001045, 0.000869, 0.00015, 0.000951, 0.000662, 0.000631, 0.000604, 0.000709, 0.000598, 0.000639, 0.00044, 0.000288, 0.000666, 0.00051, 0.000763, 0.000776, 0.000945, 0.000946, 0.000732, 0.000788, 0.001809, 0.001703, 0.000402, 0.001103, 0.000869, 0.00093, 0.000495, 0.000223, 0.000933, 0.000788, 0.000873, 0.00055, 0.000232, 0.000492, 0.00036, 0.000139, 0.000524, 0.000137, 0.000379, 0.000324, 0.000394, 0.000778, 0.000363, 0.000532, 0.000457, 0.001099, 0.000502, 0.000299, 0.000376, 0.000364, 0.000449, 0.000818, 0.000292, 0.000711, 0.000157, 0.000971, 0.001605, 0.001201, 0.000134, 0.000377, 0.000835, 0.000477, 0.000548, 0.000753, 0.000416, 0.000659, 0.000564, 0.000275, 0.000143, 0.000058, 0.0006, 0.000223, 0.000082, 0.000117, 0.00047, 0.000364, 0.000407, 0.000347, 0.000363, 0.000337, 0.000275, 0.000178, 0.000329, 0.000248, 0.000212, 0.000138, 0.000322, 0.000306, 0.000242, 0.000213, 0.000925, 0.00076, 0.000455, 0.000911, 0.000256, 0.000321, 0.000378, 0.000436, 0.000245, 0.000477, 0.000164, 0.000123, 0.000095, 0.0001, 0.000098, 0.000099, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000097, 0.000097, 0.000097]; - - -//create random phase values -var rPhase = [fftSize]; -for (let i = 0; i < fftSize; i ++) { - rPhase[i] = (((Math.random()) * 2) - 1) * .1; - rPhase[i] = rPhase[i].toFixed(2); - //console.log(rPhase[i]); -} - -var spectrum = new Float64Array(fftSize * 2); -//we just need half of this... -console.log(spectrum.length); - class SpectralFilter extends AudioWorkletProcessor { // When constructor() undefined, the default constructor will be // implicitly used. //let FFT = ssfft.FFT, RFFT = ssfft.RFFT; + constructor() { + // The super constructor call is required. + super() + //declare circular buffer + this.inputCircBuffer = new Array(1024).fill(0); + this.outputCircBuffer = new Array(1024).fill(0); + this.pointers = [0,128]; + + //declare fft stuff + this.fftSize = 256; + this.fft = new FFT(this.fftSize); // Complex FFT + this.hopSize = this.fftSize / 2; + this.hopCounter = 0; + + //this.arrayFiller = new Array(256).fill(0); + + //our spectral data from our NFT + this.nftData = [0.255795, 2.180136, 3.209771, 2.731534, 1.820246, 1.495044, 3.272544, 2.310845, 5.144471, 2.91, 0.919624, 0.34142, 0.679509, 0.381155, 0.636831, 1.160013, 0.094173, 0.193721, 0.150465, 0.12147, 0.099303, 0.09309, 0.098961, 0.066721, 0.028414, 0.059244, 0.033274, 0.024482, 0.041223, 0.025929, 0.019325, 0.05797, 0.099241, 0.126397, 0.080319, 0.07242, 0.046754, 0.020103, 0.04397, 0.021902, 0.022018, 0.013881, 0.007026, 0.000497, 0.003684, 0.006626, 0.012554, 0.007694, 0.006612, 0.014619, 0.008457, 0.003559, 0.007018, 0.00406, 0.00762, 0.019043, 0.030558, 0.021751, 0.041281, 0.033161, 0.018786, 0.009123, 0.014886, 0.010089, 0.002634, 0.016033, 0.015593, 0.019621, 0.011461, 0.030579, 0.017091, 0.017846, 0.031331, 0.02156, 0.011481, 0.017571, 0.015572, 0.032011, 0.02798, 0.024011, 0.00675, 0.003581, 0.010511, 0.007497, 0.004385, 0.002594, 0.0028, 0.000956, 0.002014, 0.002165, 0.001523, 0.001887, 0.00179, 0.001908, 0.002222, 0.003154, 0.000279, 0.001348, 0.00312, 0.002663, 0.001165, 0.000662, 0.001085, 0.000368, 0.000632, 0.000674, 0.000168, 0.000505, 0.000188, 0.000244, 0.000747, 0.000747, 0.000208, 0.000918, 0.000907, 0.000504, 0.000223, 0.001154, 0.000298, 0.000362, 0.000793, 0.000194, 0.000145, 0.00024, 0.001135, 0.00091, 0.000892, 0.00055, 0.000101, 0.000349, 0.000395, 0.000585, 0.00098, 0.001045, 0.000869, 0.00015, 0.000951, 0.000662, 0.000631, 0.000604, 0.000709, 0.000598, 0.000639, 0.00044, 0.000288, 0.000666, 0.00051, 0.000763, 0.000776, 0.000945, 0.000946, 0.000732, 0.000788, 0.001809, 0.001703, 0.000402, 0.001103, 0.000869, 0.00093, 0.000495, 0.000223, 0.000933, 0.000788, 0.000873, 0.00055, 0.000232, 0.000492, 0.00036, 0.000139, 0.000524, 0.000137, 0.000379, 0.000324, 0.000394, 0.000778, 0.000363, 0.000532, 0.000457, 0.001099, 0.000502, 0.000299, 0.000376, 0.000364, 0.000449, 0.000818, 0.000292, 0.000711, 0.000157, 0.000971, 0.001605, 0.001201, 0.000134, 0.000377, 0.000835, 0.000477, 0.000548, 0.000753, 0.000416, 0.000659, 0.000564, 0.000275, 0.000143, 0.000058, 0.0006, 0.000223, 0.000082, 0.000117, 0.00047, 0.000364, 0.000407, 0.000347, 0.000363, 0.000337, 0.000275, 0.000178, 0.000329, 0.000248, 0.000212, 0.000138, 0.000322, 0.000306, 0.000242, 0.000213, 0.000925, 0.00076, 0.000455, 0.000911, 0.000256, 0.000321, 0.000378, 0.000436, 0.000245, 0.000477, 0.000164, 0.000123, 0.000095, 0.0001, 0.000098, 0.000099, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000097, 0.000097, 0.000097]; + + //create random phase values + this.rPhase = [this.fftSize]; + for (let i = 0; i < this.fftSize; i ++) { + this.rPhase[i] = (((Math.random()) * 2) - 1) * .1; + this.rPhase[i] = this.rPhase[i].toFixed(2); + //console.log(rPhase[i]); + } + //create an array to store spectral data + this.spectrum = new Float64Array(this.fftSize * 2); + //push our magnitude and phase values into the array interleaved + this.spectrum = this.nftData.reduce((x, y, z) => (x.splice(z * 2, 0, y), x), this.rPhase.slice()); + //fill the other half with zeros + this.spectrum = this.spectrum.concat(this.arrayFiller); + //worklets' precious buffersize + this.buffersize = 128; + this.fftResult = new Float64Array(this.fftSize * 2); + } process(inputs, outputs) { // By default, the node has single input and output. const input = inputs[0]; const output = outputs[0]; - for (let channel = 0; channel < output.length; ++channel) { - const inputChannel = input[channel]; - const outputChannel = output[channel]; - - for (let i = 0; i < inputChannel.length; ++i) { - outputChannel[i] = inputChannel[i] * .1; - } - + //for (let channel = 0; channel < output.length; ++channel) { + const inputChannel = input[0]; + const outputChannel = output[0]; + + //const outputChannel2 = output[1]; + + for (let i = 0; i < inputChannel.length; ++i) { + //write a sample into the input circular buffer-- we actually only need to do this if we were taking an fft first + //this.inputCircBuffer[this.pointers[0]] = inputChannel[i]; + //increment the write pointer but wraparound + //this.pointers[0] = (this.pointers[0] + 1) % this.inputCircBuffer.length; + //increment the hopcounter until we get a hopSize amount of samples + this.hopCounter++; + if (this.hopCounter === this.hopSize) { + this.hopCounter = 0; + //do fft stuff + this.fft.ifft(this.spectrum, this.fftResult); + //add real values (every other in this interleaved list) to the outputCircBuffer + for (let n = 0; n < this.fftResult.length; n+=2) { + //and don't forget to scale by fftSize! //we also need to add a window here too but that shall wait a night + this.outputCircBuffer[this.pointers[1]] = this.outputCircBuffer[this.pointers[1]] + this.fftResult[n] / 256; + this.pointers[1] = (this.pointers[1] + 1) % this.outputCircBuffer.length; + } + //increment our outputCircBuffer pointer by one hop hopSize + this.pointers[1] = (this.pointers[1] + this.hopSize) % this.outputCircBuffer.length; + } + //console.log(this.pointers[0]); + //outputChannel[i] = inputChannel[i] * .1; + outputChannel[i] = this.outputCircBuffer[this.pointers[0]]; + this.outputCircBuffer[this.pointers[0]] = 0; + this.pointers[0] = (this.pointers[0] + 1) % this.outputCircBuffer.length; } - return true; } } From f19d714b80a61a936df5f1431f07182054aabfb1 Mon Sep 17 00:00:00 2001 From: tommy martinez Date: Thu, 11 Aug 2022 22:13:05 -0400 Subject: [PATCH 5/5] fft-test_not_working --- package.json | 1 + public/worklet/spc.js | 82 ++++++++++++++-------- src/App.js | 2 +- src/Player.js | 10 +-- src/main.js | 3 +- yarn.lock | 153 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 209 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 673dadb..39eeca2 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@babel/runtime": "^7.18.9", + "@tensorflow/tfjs": "^3.19.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", diff --git a/public/worklet/spc.js b/public/worklet/spc.js index 94e83ac..f22e5aa 100644 --- a/public/worklet/spc.js +++ b/public/worklet/spc.js @@ -1,5 +1,9 @@ // A fairly small and neat FFT - not the fastest, but not terrible // Expects interleaved complex pairs (i.e. `[real0, imag0, real1, imag1, ...]`) + + +//const model = tf.sequential(); + function FFT(size) { if (!(this instanceof FFT)) return new FFT(size); @@ -161,12 +165,9 @@ if (typeof module === 'object' && module) { }; } -class SpectralFilter extends AudioWorkletProcessor { - // When constructor() undefined, the default constructor will be - // implicitly used. - //let FFT = ssfft.FFT, RFFT = ssfft.RFFT; + +class SpectralSynth extends AudioWorkletProcessor { constructor() { - // The super constructor call is required. super() //declare circular buffer this.inputCircBuffer = new Array(1024).fill(0); @@ -174,32 +175,48 @@ class SpectralFilter extends AudioWorkletProcessor { this.pointers = [0,128]; //declare fft stuff - this.fftSize = 256; - this.fft = new FFT(this.fftSize); // Complex FFT + this.fftSize = 128; + this.fft = new RFFT(this.fftSize); // Complex FFT this.hopSize = this.fftSize / 2; this.hopCounter = 0; - - //this.arrayFiller = new Array(256).fill(0); - + this.arrayFiller = new Array(256).fill(0); //our spectral data from our NFT - this.nftData = [0.255795, 2.180136, 3.209771, 2.731534, 1.820246, 1.495044, 3.272544, 2.310845, 5.144471, 2.91, 0.919624, 0.34142, 0.679509, 0.381155, 0.636831, 1.160013, 0.094173, 0.193721, 0.150465, 0.12147, 0.099303, 0.09309, 0.098961, 0.066721, 0.028414, 0.059244, 0.033274, 0.024482, 0.041223, 0.025929, 0.019325, 0.05797, 0.099241, 0.126397, 0.080319, 0.07242, 0.046754, 0.020103, 0.04397, 0.021902, 0.022018, 0.013881, 0.007026, 0.000497, 0.003684, 0.006626, 0.012554, 0.007694, 0.006612, 0.014619, 0.008457, 0.003559, 0.007018, 0.00406, 0.00762, 0.019043, 0.030558, 0.021751, 0.041281, 0.033161, 0.018786, 0.009123, 0.014886, 0.010089, 0.002634, 0.016033, 0.015593, 0.019621, 0.011461, 0.030579, 0.017091, 0.017846, 0.031331, 0.02156, 0.011481, 0.017571, 0.015572, 0.032011, 0.02798, 0.024011, 0.00675, 0.003581, 0.010511, 0.007497, 0.004385, 0.002594, 0.0028, 0.000956, 0.002014, 0.002165, 0.001523, 0.001887, 0.00179, 0.001908, 0.002222, 0.003154, 0.000279, 0.001348, 0.00312, 0.002663, 0.001165, 0.000662, 0.001085, 0.000368, 0.000632, 0.000674, 0.000168, 0.000505, 0.000188, 0.000244, 0.000747, 0.000747, 0.000208, 0.000918, 0.000907, 0.000504, 0.000223, 0.001154, 0.000298, 0.000362, 0.000793, 0.000194, 0.000145, 0.00024, 0.001135, 0.00091, 0.000892, 0.00055, 0.000101, 0.000349, 0.000395, 0.000585, 0.00098, 0.001045, 0.000869, 0.00015, 0.000951, 0.000662, 0.000631, 0.000604, 0.000709, 0.000598, 0.000639, 0.00044, 0.000288, 0.000666, 0.00051, 0.000763, 0.000776, 0.000945, 0.000946, 0.000732, 0.000788, 0.001809, 0.001703, 0.000402, 0.001103, 0.000869, 0.00093, 0.000495, 0.000223, 0.000933, 0.000788, 0.000873, 0.00055, 0.000232, 0.000492, 0.00036, 0.000139, 0.000524, 0.000137, 0.000379, 0.000324, 0.000394, 0.000778, 0.000363, 0.000532, 0.000457, 0.001099, 0.000502, 0.000299, 0.000376, 0.000364, 0.000449, 0.000818, 0.000292, 0.000711, 0.000157, 0.000971, 0.001605, 0.001201, 0.000134, 0.000377, 0.000835, 0.000477, 0.000548, 0.000753, 0.000416, 0.000659, 0.000564, 0.000275, 0.000143, 0.000058, 0.0006, 0.000223, 0.000082, 0.000117, 0.00047, 0.000364, 0.000407, 0.000347, 0.000363, 0.000337, 0.000275, 0.000178, 0.000329, 0.000248, 0.000212, 0.000138, 0.000322, 0.000306, 0.000242, 0.000213, 0.000925, 0.00076, 0.000455, 0.000911, 0.000256, 0.000321, 0.000378, 0.000436, 0.000245, 0.000477, 0.000164, 0.000123, 0.000095, 0.0001, 0.000098, 0.000099, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000098, 0.000097, 0.000097, 0.000097]; + this.nftData = [-0.680157, -2.595802, -2.23181, 1.043628, 0.871478, 0.032085, 0.011783, -0.160232, -0.184497, -0.109513, -0.087528, -0.075393, 0.184206, 0.174413, 0.029763, -0.027556, -0.045465, -0.021071, 0.004307, 0.0381, 0.040553, 0.012664, 0.035117, -0.012051, -0.019118, 0.004216, 0.018444, 0.015699, 0.00379, -0.004722, -0.000858, -0.017687, -0.026178, 0.011752, 0.019912, 0.013626, 0.00343, -0.046204, -0.047157, -0.009494, 0.007517, 0.001061, 0.001682, -0.001973, 0.00136, -0.000763, -0.008926, 0.001992, 0.008029, -0.006005, -0.000749, 0.001227, 0.000536, -0.000417, 0.001444, 0.000586, -0.00084, 0.00056, 0.002605, 0.000054, 0.000127, 0.001656, 0.00143, -0.00008, -0.004751, -0.004541, 0.000775, 0.000517, 0.001907, 0.000662, 0.000421, -0.000034, 0.001203, -0.000295, -0.000875, -0.000185, 0.001125, 0.00154, 0.000368, -0.000635, 0.001205, 0.000953, 0.000298, -0.00007, 0.000814, 0.000101, -0.000163, 0.000154, 0.000806, -0.000091, 0.00047, 0.000528, 0.000385, 0.000568, -0.000065, -0.002443, -0.000881, 0.000015, 0.000921, 0.00154, 0.000318, -0.000622, 0.000688, -0.000106, -0.000524, -0.000082, 0.000407, -0.000157, -0.000026, 0.000186, 0.000851, -0.001358, -0.001375, -0.001035, -0.00129, -0.00054, -0.000292, -0.000539, 0.000184, -0.000136, 0.000128, -0.000125, 0.000123, -0.000122, 0.000121, -0.00012, 0.00012, -0.00012]; + + for (let i = 0; i < this.fftSize; i ++) { + //this.nftData[i] = (((Math.random()) * 2) - 1) * .4; + this.nftData[i] = parseFloat(this.nftData[i].toFixed(2)); + //console.log(rPhase[i]); + } //create random phase values this.rPhase = [this.fftSize]; for (let i = 0; i < this.fftSize; i ++) { - this.rPhase[i] = (((Math.random()) * 2) - 1) * .1; - this.rPhase[i] = this.rPhase[i].toFixed(2); + this.rPhase[i] = (((Math.random()) * 2) - 1) * .4; + this.rPhase[i] = parseFloat(this.rPhase[i].toFixed(2)); //console.log(rPhase[i]); } - //create an array to store spectral data - this.spectrum = new Float64Array(this.fftSize * 2); + + //this.rPhase = [0., -0.157171, -2.327943, -1.563757, 0.121738, -0.4125, 0.15856, 1.156681, 0.314372, -1.141282, -0.701739, 0.167129, -0.223753, 0.55177, 2.264441, 0.934212, -0.31556, -0.030361, -0.09366, -0.096043, -0.029978, -0.00103, 0.075803, 0.055411, -0.066573, 0.019619, 0.050953, 0.020653, 0.017562, 0.047335, 0.014223, -0.014835, -0.007107, -0.003508, 0.008877, -0.018271, -0.01674, 0.008487, -0.007421, 0.024174, 0.014349, -0.020094, 0.001163, 0.026269, 0.015633, -0.005191, -0.016158, -0.013792, -0.00482, 0.000845, 0.002349, 0.007815, 0.006865, 0.009279, 0.001811, -0.006692, -0.00348, 0.001848, -0.00081, 0.000704, 0.005282, -0.000777, -0.004505, -0.006024, -0.002743, -0.000259, -0.000884, 0.000035, -0.001038, 0.000416, 0.000283, -0.000087, 0.002783, 0.00029, -0.00141, 0.000487, 0.000617, 0.004585, 0.003632, 0.001466, -0.003343, -0.008486, -0.005811, -0.001335, 0.005784, 0.006047, 0.004387, 0.003335, -0.000633, -0.001485, -0.000222, 0.000151, -0.000441, 0.000457, -0.000951, -0.000842, -0.00104, -0.000729, 0.000481, 0.00192, -0.000705, -0.001682, 0.000225, 0.000926, 0.001278, 0.002523, 0.001809, -0.000616, -0.001093, -0.001666, -0.000765, -0.000816, -0.000757, 0.00168, 0.001204, 0.000326, -0.000187, -0.002533, -0.001162, 0.001145, 0.002293, 0.002692, 0.002577, 0.001273, -0.00154, -0.003063, 0.000033, 0.001685, 0.000712, -0.000198, -0.002081, 0.000084, 0.001235, 0.00008, 0.000922, 0.001146, -0.00071, 0.000268, 0.000194, -0.000088, 0.001296, 0.001478, 0.00155, 0.00096, 0.001434, 0.000761, -0.00029, -0.000269, -0.001582, -0.001472, -0.000668, -0.00107, -0.000022, 0.000134, -0.000928, 0.001478, 0.002479, 0.001363, 0.00494, 0.003122, 0.001226, 0.001315, -0.00535, -0.004939, -0.000615, 0.000082, 0.005576, 0.010053, 0.002079, -0.006258, -0.004817, -0.003365, -0.001602, 0.000514, 0.000837, -0.000036, -0.001176, 0.000227, -0.001142, -0.002114, -0.000668, -0.00038, 0.000351, 0.000276, 0.00133, 0.002064, -0.000704, -0.003125, -0.001721, -0.000144, -0.000047, 0.000995, -0.000032, -0.000805, 0.001206, 0.001334, -0.000698, 0.000632, 0.000079, 0.000056, 0.002389, 0.00038, -0.00125, 0.000793, 0.001168, 0.000011, -0.00105, -0.001989, -0.001727, -0.000799, -0.000884, -0.000259, 0.000542, 0.000138, -0.000541, -0.001258, -0.000429, 0.000717, 0.000997, 0.000809, 0.000909, 0.000168, 0.002851, 0.004202, 0.000647, -0.001126, -0.002, -0.001404, -0.000953, -0.001392, -0.000513, 0.000157, -0.000022, -0.000168, -0.000025, 0.000005, -0.000014, 0.000001, -0.000001, 0.000004, -0.000002, 0.000001, -0.000001, 0.000001, -0.000001, 0., -0., 0., -0., 0., -0., 0., -0., 0., -0., 0., 0., -0., 0., -0., 0., -0., 0., -0., 0., -0., 0., -0., 0.000001, -0.000001, 0.000001, -0.000001, 0.000002, -0.000004, 0.000001, -0.000001, 0.000014, -0.000005, 0.000025, 0.000168, 0.000022, -0.000157, 0.000513, 0.001392, 0.000953, 0.001404, 0.002, 0.001126, -0.000647, -0.004202, -0.002851, -0.000168, -0.000909, -0.000809, -0.000997, -0.000717, 0.000429, 0.001258, 0.000541, -0.000138, -0.000542, 0.000259, 0.000884, 0.000799, 0.001727, 0.001989, 0.00105, -0.000011, -0.001168, -0.000793, 0.00125, -0.00038, -0.002389, -0.000056, -0.000079, -0.000632, 0.000698, -0.001334, -0.001206, 0.000805, 0.000032, -0.000995, 0.000047, 0.000144, 0.001721, 0.003125, 0.000704, -0.002064, -0.00133, -0.000276, -0.000351, 0.00038, 0.000668, 0.002114, 0.001142, -0.000227, 0.001176, 0.000036, -0.000837, -0.000514, 0.001602, 0.003365, 0.004817, 0.006258, -0.002079, -0.010053, -0.005576, -0.000082, 0.000615, 0.004939, 0.00535, -0.001315, -0.001226, -0.003122, -0.00494, -0.001363, -0.002479, -0.001478, 0.000928, -0.000134, 0.000022, 0.00107, 0.000668, 0.001472, 0.001582, 0.000269, 0.00029, -0.000761, -0.001434, -0.00096, -0.00155, -0.001478, -0.001296, 0.000088, -0.000194, -0.000268, 0.00071, -0.001146, -0.000922, -0.00008, -0.001235, -0.000084, 0.002081, 0.000198, -0.000712, -0.001685, -0.000033, 0.003063, 0.00154, -0.001273, -0.002577, -0.002692, -0.002293, -0.001145, 0.001162, 0.002533, 0.000187, -0.000326, -0.001204, -0.00168, 0.000757, 0.000816, 0.000765, 0.001666, 0.001093, 0.000616, -0.001809, -0.002523, -0.001278, -0.000926, -0.000225, 0.001682, 0.000705, -0.00192, -0.000481, 0.000729, 0.00104, 0.000842, 0.000951, -0.000457, 0.000441, -0.000151, 0.000222, 0.001485, 0.000633, -0.003335, -0.004387, -0.006047, -0.005784, 0.001335, 0.005811, 0.008486, 0.003343, -0.001466, -0.003632, -0.004585, -0.000617, -0.000487, 0.00141, -0.00029, -0.002783, 0.000087, -0.000283, -0.000416, 0.001038, -0.000035, 0.000884, 0.000259, 0.002743, 0.006024, 0.004505, 0.000777, -0.005282, -0.000704, 0.00081, -0.001848, 0.00348, 0.006692, -0.001811, -0.009279, -0.006865, -0.007815, -0.002349, -0.000845, 0.00482, 0.013792, 0.016158, 0.005191, -0.015633, -0.026269, -0.001163, 0.020094, -0.014349, -0.024174, 0.007421, -0.008487, 0.01674, 0.018271, -0.008877, 0.003508, 0.007107, 0.014835, -0.014223, -0.047335, -0.017562, -0.020653, -0.050953, -0.019619, 0.066573, -0.055411, -0.075803, 0.00103, 0.029978, 0.096043, 0.09366, 0.030361, 0.31556, -0.934212, -2.264441, -0.55177, 0.223753, -0.167129, 0.701739, 1.141282, -0.314372, -1.156681, -0.15856, 0.4125, -0.121738, 1.563757, 2.327943, 0.157171]; + + //create an array to store spectral data, this array contains real and imag so is 2x fftSize + this.spectrum = new Float64Array(this.fftSize); //push our magnitude and phase values into the array interleaved this.spectrum = this.nftData.reduce((x, y, z) => (x.splice(z * 2, 0, y), x), this.rPhase.slice()); //fill the other half with zeros - this.spectrum = this.spectrum.concat(this.arrayFiller); + //this.spectrum = this.spectrum.concat(this.arrayFiller); //worklets' precious buffersize this.buffersize = 128; - this.fftResult = new Float64Array(this.fftSize * 2); + this.fftResult = new Float64Array(this.fftSize) ; + //window function + function hanning (i, N) { + return 0.5*(1 - Math.cos(6.283185307179586*i/(N-1))) + } + //fills this.hann array with window + this.hann = [this.fftSize]; + for (let y = 0; y < this.fftSize; y++) { + this.hann[y] = hanning(y,this.fftSize); + } } process(inputs, outputs) { @@ -213,11 +230,9 @@ class SpectralFilter extends AudioWorkletProcessor { //const outputChannel2 = output[1]; + /* for (let i = 0; i < inputChannel.length; ++i) { - //write a sample into the input circular buffer-- we actually only need to do this if we were taking an fft first - //this.inputCircBuffer[this.pointers[0]] = inputChannel[i]; - //increment the write pointer but wraparound - //this.pointers[0] = (this.pointers[0] + 1) % this.inputCircBuffer.length; + //do nothing with our input sample, this is used to keep the worklet active(check accuracy) //increment the hopcounter until we get a hopSize amount of samples this.hopCounter++; if (this.hopCounter === this.hopSize) { @@ -227,20 +242,33 @@ class SpectralFilter extends AudioWorkletProcessor { //add real values (every other in this interleaved list) to the outputCircBuffer for (let n = 0; n < this.fftResult.length; n+=2) { //and don't forget to scale by fftSize! //we also need to add a window here too but that shall wait a night - this.outputCircBuffer[this.pointers[1]] = this.outputCircBuffer[this.pointers[1]] + this.fftResult[n] / 256; + this.outputCircBuffer[this.pointers[1]] = (this.outputCircBuffer[this.pointers[1]] + this.fftResult[n]) / this.fftSize; this.pointers[1] = (this.pointers[1] + 1) % this.outputCircBuffer.length; } //increment our outputCircBuffer pointer by one hop hopSize - this.pointers[1] = (this.pointers[1] + this.hopSize) % this.outputCircBuffer.length; + //this.pointers[1] = (this.pointers[1] + this.hopSize) % this.outputCircBuffer.length; } //console.log(this.pointers[0]); //outputChannel[i] = inputChannel[i] * .1; - outputChannel[i] = this.outputCircBuffer[this.pointers[0]]; - this.outputCircBuffer[this.pointers[0]] = 0; - this.pointers[0] = (this.pointers[0] + 1) % this.outputCircBuffer.length; + outputChannel[i] = this.outputCircBuffer[this.pointers[0] + i]; + //console.log(this.outputCircBuffer[this.pointers[0] + i]); + this.outputCircBuffer[this.pointers[0] + i] = 0; + //console.log(this.outputCircBuffer[this.pointers[0] + i]); + this.pointers[0] = (this.pointers[0] + 1) % this.outputCircBuffer.length + } + */ + this.fft.fft(inputChannel, this.fftResult); + this.fft.ifft(this.nftData, outputChannel); + for (let i = 0; i < inputChannel.length; ++i) { + outputChannel[i] = outputChannel[i] / this.fftSize; + } + + console.log(this.fftResult); + //console.log(this.nftData.length); + //console.log(this.pointers[0]); return true; } } -registerProcessor('spectralfilter', SpectralFilter); +registerProcessor('spectralsynth', SpectralSynth); diff --git a/src/App.js b/src/App.js index 2eb7061..6e24f70 100644 --- a/src/App.js +++ b/src/App.js @@ -9,7 +9,7 @@ function App() {
{/*logo */}

- Spectrum-Writer is a Web3 music composition tool. + Spectrum-Writer is a collaborative music composition tool.

diff --git a/src/Player.js b/src/Player.js index 683e611..941e300 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,11 +1,10 @@ import React from 'react'; + + class Player extends React.Component { constructor(props) { super(props); - - //this.onMove = this.onMove.bind(this); - //this.testVarible= "this is a test"; } @@ -16,21 +15,18 @@ class Player extends React.Component { oscillator.frequency.value = 450; oscillator.frequency.amplitude = .1; await context.audioWorklet.addModule('worklet/spc.js') - console.log('i did it'); - const spectralNode = new window.AudioWorkletNode(context, 'spectralfilter'); + const spectralNode = new window.AudioWorkletNode(context, 'spectralsynth'); oscillator.connect(spectralNode).connect(context.destination); oscillator.start(); } processSomeStuff(); } - render() { return (

- ); } } diff --git a/src/main.js b/src/main.js index 2dd32c0..a045942 100644 --- a/src/main.js +++ b/src/main.js @@ -8,8 +8,7 @@ function updateFilter(slidey){ async function processSomeStuff(){ context = new AudioContext(); - - const audio = new Audio("./sounds/overhere.wav"); + //const audio = new Audio("./sounds/overhere.wav"); /* const oscillator = new OscillatorNode(context); oscillator.frequency.value = 450; diff --git a/yarn.lock b/yarn.lock index 223995f..a655428 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2031,6 +2031,76 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@tensorflow/tfjs-backend-cpu@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-3.19.0.tgz#c7524ccdfded81df0c5cb53185b14e5222ac51e5" + integrity sha512-02f+WkiL9gc9G7P8PwfsvuXREcAUdM/3uAL6fTle3xKEj7KOxX+E/mc3jxPY5UzjAsgHVBZrPJ2xi6AG16WPkQ== + dependencies: + "@types/seedrandom" "^2.4.28" + seedrandom "^3.0.5" + +"@tensorflow/tfjs-backend-webgl@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-3.19.0.tgz#64b8a14df35ee7d27859c7d141c527cefc6d9484" + integrity sha512-2HTkAE21t3WQTt8P6iK80ni03AzC8UNZmbIB7/pBDYBbhDwZwe/C5fXrJWnP9m6u4hvCdMAJ3o+OP3NeaEL1pw== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.19.0" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "^2.4.28" + "@types/webgl-ext" "0.0.30" + "@types/webgl2" "0.0.6" + seedrandom "^3.0.5" + +"@tensorflow/tfjs-converter@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-converter/-/tfjs-converter-3.19.0.tgz#701db7255ef45578811a191478db5a09bcca6dda" + integrity sha512-B69HQq9/orsM8pGJPjNp1cV+hIcc90mxcRIsQSYGovTUNEcftmz2Sh+mqXDWysKUk0gRfx5CX6eJk6NaE55Xow== + +"@tensorflow/tfjs-core@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-core/-/tfjs-core-3.19.0.tgz#981c50bb38a6441a4375cfc8806784e7490f01bc" + integrity sha512-znJ+TOJ3NdNL5yjw8M7dn2jO96sokiH1wfFuD7gglCkbZ4SXlFpFj2xelNdRHHmeYanMhJzqeyOW9whUnNcBqw== + dependencies: + "@types/long" "^4.0.1" + "@types/offscreencanvas" "~2019.3.0" + "@types/seedrandom" "^2.4.28" + "@types/webgl-ext" "0.0.30" + "@webgpu/types" "0.1.16" + long "4.0.0" + node-fetch "~2.6.1" + seedrandom "^3.0.5" + +"@tensorflow/tfjs-data@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-data/-/tfjs-data-3.19.0.tgz#31de23cbea6cc594d60bd2216ab39faa8b2219cb" + integrity sha512-rkZv+YZowZwnm4RaedkV44WDrjokRHld9Py/0Fb7IvMyUh37lY0WsAsV94kJ+QuLc6iVNcDLaV29K+dUz57bRA== + dependencies: + "@types/node-fetch" "^2.1.2" + node-fetch "~2.6.1" + string_decoder "^1.3.0" + +"@tensorflow/tfjs-layers@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs-layers/-/tfjs-layers-3.19.0.tgz#b624c25a2bdec09ea1c71db6547eb0952707fb35" + integrity sha512-+sVWjWWyTuT3sImrtNLtMv8/4FS30GAYpTgyJKhCQ3+GSvHUXulxJfncD0QqOg9fTbhtuF1TRAkzDU8v64791g== + +"@tensorflow/tfjs@^3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@tensorflow/tfjs/-/tfjs-3.19.0.tgz#a08c35e6101bdbc0bf9a58f468270eee15f77bb0" + integrity sha512-fZF3HOON8jgKhFk06WIScIXf7j/gkl6cLbU1brFWutBhHlPSzxSWvdJR/TivCK7p+yMBunoyK50TjiwOrcoclA== + dependencies: + "@tensorflow/tfjs-backend-cpu" "3.19.0" + "@tensorflow/tfjs-backend-webgl" "3.19.0" + "@tensorflow/tfjs-converter" "3.19.0" + "@tensorflow/tfjs-core" "3.19.0" + "@tensorflow/tfjs-data" "3.19.0" + "@tensorflow/tfjs-layers" "3.19.0" + argparse "^1.0.10" + chalk "^4.1.0" + core-js "3" + regenerator-runtime "^0.13.5" + yargs "^16.0.3" + "@testing-library/dom@^8.5.0": version "8.16.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.16.0.tgz#d6fc50250aed17b1035ca1bd64655e342db3936a" @@ -2260,16 +2330,34 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + "@types/mime@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.0.tgz#e9a9903894405c6a6551f1774df4e64d9804d69c" integrity sha512-fccbsHKqFDXClBZTDLA43zl0+TbxyIwyzIzwwhvoJvhNjOErCdeX2xJbURimv2EbSVUGav001PaCJg4mZxMl4w== +"@types/node-fetch@^2.1.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "18.6.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.3.tgz#4e4a95b6fe44014563ceb514b2598b3e623d1c98" integrity sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg== +"@types/offscreencanvas@~2019.3.0": + version "2019.3.0" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz#3336428ec7e9180cf4566dfea5da04eb586a6553" + integrity sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -2333,6 +2421,11 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/seedrandom@^2.4.28": + version "2.4.30" + resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.30.tgz#d2efe425869b84163c2d56e779dddadb9372cbfa" + integrity sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ== + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -2372,6 +2465,16 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== +"@types/webgl-ext@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d" + integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg== + +"@types/webgl2@0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.6.tgz#1ea2db791362bd8521548d664dbd3c5311cdf4b6" + integrity sha512-50GQhDVTq/herLMiqSQkdtRu+d5q/cWHn4VvKJtrj4DJAjo1MNkWYa2MA41BaBO1q1HgsUjuQvEOk0QHvlnAaQ== + "@types/ws@^8.5.1": version "8.5.3" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" @@ -2606,6 +2709,11 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@webgpu/types@0.1.16": + version "0.1.16" + resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.1.16.tgz#1f05497b95b7c013facf7035c8e21784645f5cc4" + integrity sha512-9E61voMP4+Rze02jlTXud++Htpjyyk8vw5Hyw9FGRrmhHQg2GqbuOfwf5Klrb8vTxc2XWI3EfO7RUHMpxTj26A== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -2789,7 +2897,7 @@ arg@^5.0.2: resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== -argparse@^1.0.7: +argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -3527,7 +3635,7 @@ core-js-pure@^3.20.2, core-js-pure@^3.8.1: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.24.1.tgz#8839dde5da545521bf282feb7dc6d0b425f39fd3" integrity sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg== -core-js@^3.19.2: +core-js@3, core-js@^3.19.2: version "3.24.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f" integrity sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg== @@ -6325,6 +6433,11 @@ lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +long@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -6550,6 +6663,13 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-fetch@~2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -7829,7 +7949,7 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5, regenerator-runtime@^0.13.9: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== @@ -8096,6 +8216,11 @@ scrypt-js@3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +seedrandom@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" + integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -8425,7 +8550,7 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -8734,6 +8859,11 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -8985,6 +9115,11 @@ web-vitals@^2.1.4: resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c" integrity sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -9136,6 +9271,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" @@ -9427,7 +9570,7 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs@^16.2.0: +yargs@^16.0.3, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==