Changed how listening to ranges of a visualizer works.

This commit is contained in:
Harrison Deng 2022-04-17 02:29:40 -05:00
parent 45093faf4e
commit bf3cef97be
2 changed files with 51 additions and 25 deletions

View File

@ -14,20 +14,22 @@ import VisualizerUpdateManager from "../visualization/VisualizerUpdateManager.js
* Maps the red component of the text color to a certain range of bins.
*
* @param {HTMLElement} element The element whose text's red value should be mapped.
* @param {number} color Where 0 for red, 1, for blue, 2 for green, and 3 for alpha.
* @param {number} min The lower bound of the bins to be mapped.
* @param {number} color Where r for red, g, for green, b for blue, and a for alpha.
* @param {number} lowerBin The lower bound of the bins to be mapped.
* @param {VisualizerUpdateManager} visUpdateManager The visualizer update manager associated with the audio playback you would like the mapping with.
* @param {interpolator} interpolator The interpolation function to use.
* @param {number} [max=undefined] The upper bound of the bins to be mapped. If left undefined, then only the bin defined by the min value is used.
* @param {number} [upperBin=undefined] The upper bound of the bins to be mapped. If left undefined, then only the bin defined by the min value is used.
* @param {boolean} [reversed=true] If true, then the quieter, the greater the red value.
*/
export function mapColor(element, color, min, visUpdateManager, interpolator, max = undefined, reversed = false) {
if (!max) max = min;
visUpdateManager.addVisualizerRangeUpdateListener(min, max, (timeDelta, amp) => {
export function mapColor(element, color, lowerBin, visUpdateManager, interpolator, upperBin = undefined, reversed = false) {
const rgbaStr = "rgba";
color = rgbaStr.indexOf(color);
if (color < 0) throw new Error("Invalid color parameter provided.");
if (!upperBin) upperBin = lowerBin;
visUpdateManager.addVisualizerRangeUpdateListener(lowerBin, upperBin, (timeDelta, amp) => {
const rgba = parseColor(element.style.color);
rgba[color] = interpolator(rgba[color], amp, timeDelta);
if (reversed) rgba[color] = 255 - rgba[color];
element.style.color = rgbaToHexRgba(rgba);
});
}

View File

@ -14,22 +14,34 @@ export default class VisualizerUpdateManager {
*/
constructor(visualizer) {
this._binnedListeners = [];
this._rangedListeners = [];
for (let i = 0; i < visualizer.getNumberOfBins(); i++) {
this._binnedListeners.push([]);
}
this._lastBins = new Uint8Array(this._binnedListeners.length);
visualizer.addUpdateListener((delta, bins) => {
this._visualizer = visualizer;
this._visualizerListener = (delta, bins) => {
const sortedCopyOfRangedListeners = [... this._rangedListeners].sort((a, b) => a[0] - b[0]); // Priority queue could be better.
for (let binInd = 0; binInd < this._lastBins.length; binInd++) {
const lastBin = this._lastBins[binInd];
if (lastBin !== bins[binInd]) {
this._binnedListeners[binInd].forEach(listener => {
listener(delta, bins[binInd], bins[binInd] - lastBin);
});
for (let rangedInd = 0; rangedInd < sortedCopyOfRangedListeners.length; rangedInd++) { // Could switch to a while loop.
const [min, max, listener] = sortedCopyOfRangedListeners[rangedInd];
if (min > binInd) break; // Don't need to check the rest if the current lowest minimum is greater than the current bin index.
if (binInd <= max) {
listener(delta, bins.slice(min, max));
sortedCopyOfRangedListeners.shift();
rangedInd--;
}
}
this._lastBins[binInd] = bins[binInd];
}
}
});
};
visualizer.addUpdateListener(this._visualizerListener);
}
/**
@ -39,12 +51,18 @@ export default class VisualizerUpdateManager {
* @param {number} ampDelta change in amplitude of the frequency bin.
*/
/**
* @callback visualizerRangeUpdateListener
* @param {number} timeDelta elapsed time since last update.
* @param {number} bins the bins of the range.
*/
/**
*
* @param {number} freqBin the frequency bin this update listener should listen to.
* @param {visualizerBinUpdateListener} listener the listener itself that will be called upon the bin updating.
* @returns {boolean} true if and only if the updater was added successfully, otherwise, false.
* @returns {boolean} true if and only if the updater was added successfully.
*/
AddVisualizerBinUpdateListener(freqBin, listener) {
if (this._binnedListeners[freqBin].includes(listener)) return false;
@ -53,19 +71,18 @@ export default class VisualizerUpdateManager {
}
/**
* Similar to {@link VisualizerUpdateManager#AddVisualizerBinUpdateListener}, this method adds the same listener to a range of bins.
* Similar to {@link VisualizerUpdateManager#AddVisualizerBinUpdateListener}, this method adds a listener for to a range of bins.
*
* @param {number} min The lower bound of the bins to listen to (inclusive).
* @param {number} max The upper bound of the bins to listen to (inclusive).
* @param {visualizerBinUpdateListener} listener The listener to register to these bins.
* @returns {boolean} True if and only if the listener was added at least once.
* @param {visualizerRangeUpdateListener} listener The listener to register to the range.
* @returns {boolean} True if and only if the ranged listener was added successfully.
*/
addVisualizerRangeUpdateListener(min, max, listener) {
let added = false;
for (let i = min; i <= max; i++) {
if (this.AddVisualizerBinUpdateListener(i, listener)) added = true;
}
return added;
const rangedListener = [min, max, listener];
if (this._rangedListeners.includes(rangedListener)) return false;
this._rangedListeners.push(rangedListener);
return true;
}
/**
@ -87,14 +104,14 @@ export default class VisualizerUpdateManager {
* @param {number} min The lower bound of bins to remove the listener from (inclusive).
* @param {number} max The upper bound of bin to remove the listener from (inclusive.)
* @param {visualizerBinUpdateListener} listener The update listener to remove from the bins.
* @returns {boolean} True if and only if at least one listener was removed.
* @returns {boolean} True if and only if the given listener was removed.
*/
removeVisualizerRangeUpdateListener(min, max, listener) {
let removed = false;
for (let i = min; i <= max; i++) {
if (this.removeVisualizerBinUpdateListener(i, listener)) removed = true;
}
return removed;
const rangedListener = [min, max, listener];
const removeIndex = this._rangedListeners.indexOf(rangedListener);
if (removeIndex < 0) return false;
this._binnedListeners.splice(removeIndex, 1);
return true;
}
/**
@ -124,4 +141,11 @@ export default class VisualizerUpdateManager {
bin.length = 0;
});
}
/**
* Unbinds this update manager from the initial visualizer. Effectively meaning this manager will no longer be used.
*/
unbindVisualizer() {
this._visualizer.removeUpdateListener(this._visualizerListener);
}
}