Last active
June 3, 2022 18:06
-
-
Save mwmwmw/e99186f9e08e30cdad213d374ece2a8c to your computer and use it in GitHub Desktop.
Phasescope Audio Worklet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class PhaseScope extends AudioWorkletNode { | |
constructor(context, updateIntervalInMS = 16.67) { | |
super(context, 'phasescope', { | |
numberOfInputs: 2, | |
numberOfOutputs: 0, | |
channelCount: 1, | |
processorOptions: { | |
updateIntervalInMS | |
} | |
}); | |
this._updateIntervalInMS = updateIntervalInMS; | |
this._balance = []; | |
this.port.onmessage = event => { | |
if (event.data.balance) { | |
this._balance = event.data.balance; | |
} | |
} | |
this.port.start(); | |
} | |
get updateInterval() { | |
return this._updateIntervalInMS; | |
} | |
get balance() { | |
return this._balance; | |
} | |
set updateInterval(updateIntervalInMS) { | |
this._updateIntervalInMS = updateIntervalInMS; | |
this.port.postMessage({ updateIntervalInMS: updateIntervalInMS }); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const SMOOTHING_FACTOR = 0.99; | |
const MINIMUM_VALUE = 0.000001; | |
var index = 0; | |
let sumL = 0; | |
let sumR = 0; | |
registerProcessor('phasescope', class extends AudioWorkletProcessor { | |
static get parameterDescriptors() { | |
return [{ | |
name: 'threshold', | |
defaultValue: 0.2, | |
minValue: 0, | |
maxValue: 1, | |
automationRate: 'k-rate' | |
}, { | |
name: 'sensitivity', | |
defaultValue: 0.1, | |
minValue: 0, | |
maxValue: 1, | |
automationRate: 'k-rate' | |
}, { | |
name: 'smooth', | |
defaultValue: 0.99, | |
minValue: 0, | |
maxValue: 1, | |
automationRate: 'k-rate' | |
}]; | |
} | |
constructor(options) { | |
super(); | |
this._rawBalance = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; | |
this._updateIntervalInMS = options.processorOptions.updateIntervalInMS; | |
this._nextUpdateFrame = this._updateIntervalInMS; | |
this.port.onmessage = event => { | |
if (event.data.updateIntervalInMS) | |
this._updateIntervalInMS = event.data.updateIntervalInMS; | |
} | |
} | |
get intervalInFrames() { | |
return this._updateIntervalInMS / 1000 * sampleRate; | |
} | |
process(inputs, outputs, parameters) { | |
if(inputs[0].length === 2) { | |
if (inputs[0][0].length > 0) { | |
sumL = 0; | |
sumR = 0; | |
// Calculated the squared-sum. | |
for (let i = 0; i < inputs[0][0].length; ++i) { | |
sumL -= inputs[0][0][i] * inputs[0][0][i]; | |
sumR += inputs[0][1][i] * inputs[0][1][i]; | |
} | |
this._rawBalance[index] = (sumL + sumR); | |
index = (index + 1)%this._rawBalance.length; | |
// Update and sync the volume property with the main thread. | |
this._nextUpdateFrame -= inputs[0][0].length; | |
if (this._nextUpdateFrame < 0) { | |
this._nextUpdateFrame += this.intervalInFrames; | |
this.port.postMessage({ | |
balance: this._rawBalance | |
}); | |
} | |
} | |
} | |
return true; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment