import BaseLfo from '../../core/BaseLfo';
const sqrt = Math.sqrt;
/**
* Compute mean and standard deviation of a given `signal`.
*
* _support `standalone` usage_
*
* @memberof module:common.operator
*
* @example
* import * as lfo from 'waves-lfo/client';
*
* const audioContext = new AudioContext();
*
* navigator.mediaDevices
* .getUserMedia({ audio: true })
* .then(init)
* .catch((err) => console.error(err.stack));
*
* function init(stream) {
* const source = audioContext.createMediaStreamSource(stream);
*
* const audioInNode = new lfo.source.AudioInNode({
* sourceNode: source,
* audioContext: audioContext,
* });
*
* const meanStddev = new lfo.operator.MeanStddev();
*
* const traceDisplay = new lfo.sink.TraceDisplay({
* canvas: '#trace',
* });
*
* audioInNode.connect(meanStddev);
* meanStddev.connect(traceDisplay);
* audioInNode.start();
* }
*/
class MeanStddev extends BaseLfo {
constructor(options = {}) {
// no options available, just throw an error if some param try to be set.
super({}, options);
}
/** @private */
processStreamParams(prevStreamParams) {
this.prepareStreamParams(prevStreamParams);
this.streamParams.frameType = 'vector';
this.streamParams.frameSize = 2;
this.streamParams.description = ['mean', 'stddev'];
this.propagateStreamParams();
}
/**
* Use the `MeanStddev` operator in `standalone` mode (i.e. outside of a graph).
*
* @param {Array|Float32Array} values - Values to process.
* @return {Array} - Mean and standart deviation of the input values.
*
* @example
* import * as lfo from 'waves-lfo/client';
*
* const meanStddev = new lfo.operator.MeanStddev();
* meanStddev.initStream({ frameType: 'vector', frameSize: 1024 });
* meanStddev.inputVector(someSineSignal);
* > [0, 0.7071]
*/
inputSignal(values) {
const outData = this.frame.data;
const length = values.length;
let mean = 0;
let m2 = 0;
// compute mean and variance with Welford algorithm
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
for (let i = 0; i < length; i++) {
const x = values[i];
const delta = x - mean;
mean += delta / (i + 1);
m2 += delta * (x - mean);
}
const variance = m2 / (length - 1);
const stddev = sqrt(variance);
outData[0] = mean;
outData[1] = stddev;
return outData;
}
/** @private */
processSignal(frame) {
this.inputSignal(frame.data);
}
}
export default MeanStddev;