90 lines
4.3 KiB
JavaScript

import VisUpdateRouter from "../visualization/VisUpdateRouter.js";
/**
*
* @callback numericalGetter
* @returns {number} The number this value currently represents.
*/
/**
* @callback numericalSetter
* @param {number} value The new numerical value to update to.
*/
// PEND: Warnings about interpolator not being defined are broken. Docs generate fine.
/**
* Maps the average of a range of bins to numerical value defined by a getter and a setter.
*
* @param {object} conf A configuration for how to map a numerical value.
* @param {number} conf.minVal The minimum value of the numerical value.
* @param {number} conf.maxVal The maximum value of the numerical value.
* @param {number} conf.lowerBin The lower bin of the range of bins this value is to be mapped to.
* @param {number} conf.upperBin The upper bin of the range of bins this value si to be mapped to.
* @param {numericalGetter} conf.getter The getter callback to be used to get the current number.
* @param {numericalSetter} conf.setter The setter callback to be used to set the new number.
* @param {interpolator} conf.interpolator The interpolation function to use.
* @param {VisUpdateRouter} conf.visUpdateRouter the visualizer update manager this mapping corresponds with.
* @param {boolean} [conf.reversed = false] If true, then high amplitudes will be mapped to low values and vice versa.
* @returns {{lower: number, upper: number, listener: VisUpdateRouter.visualizerRangedUpdateListener}} An object containing the lower and upper bounds for the range of a listener, which is also in the object.
*/
function mapRangedAvgNumerical({ minVal, maxVal, lowerBin = undefined, upperBin, getter, setter, interpolator, visUpdateRouter, reversed = false }) {
console.log("mapping average numerical.");
const rangedListener = {
lower: lowerBin,
upper: upperBin,
listener: (timeDelta, bins) => {
const normalBins = [...bins];
// TODO: Future: add weighting / distribution system?
let normAvg = 0;
for (let i = 0; i < normalBins.length; i++) {
normalBins[i] = normalBins[i] / 255.0;
normAvg += normalBins[i];
}
normAvg /= normalBins.length;
const range = maxVal - minVal;
let interpolated = interpolator((getter() - minVal) / range, normAvg, Math.min(timeDelta, 1));
if (reversed) interpolated = 1 - interpolated;
setter(minVal + range * interpolated);
}
};
if (visUpdateRouter.addVisualizerRangedUpdateListener(rangedListener)) {
return rangedListener;
}
return null; // Technically doesn't occur since the functions are anonymous?
}
/**
* Maps a single bin of frequency amplitudes to a numerical value defined by a getter and a setter.
*
* @param {object} conf The configuration for mapping a single bin to a numerical value.
* @param {number} conf.minVal The minimum value the mapping can produce.
* @param {number} conf.maxVal The maximum value the mapping can produce.
* @param {number} conf.bin The bin to map this number to.
* @param {numericalGetter} conf.getter The callback to be used to get the current number.
* @param {numericalSetter} conf.setter The callback to be used to set the new number.
* @param {interpolator} conf.interpolator The interpolation function to use.
* @param {VisUpdateRouter} conf.visUpdateRouter The update manager to map to.
* @param {boolean} [conf.reversed] If true, then high amplitudes will be mapped to lower values and vice versa.
* @returns {{bin: number, listener: VisUpdateRouter.visualizerBinUpdateListener}} The bin listener that was added.
*/
function mapBinNumerical({ minVal, maxVal, bin, getter, setter, interpolator, visUpdateRouter, reversed = false }) {
console.log("mapping numerical...");
const listener = {
bin: bin,
listener: (timeDelta, amp) => {
const range = maxVal - minVal;
let interpolated = interpolator(getter(), amp, Math.min(timeDelta, 1));
if (reversed) interpolated = 1 - interpolated;
setter(minVal + range * interpolated);
}
};
if (visUpdateRouter.AddVisualizerBinUpdateListener(listener)) {
return listener;
}
return null; // Technically doesn't occur since the functions are anonymous?
}
export { mapRangedAvgNumerical, mapBinNumerical };