Visualizer now no longer immediately instantiates audio context.

This commit is contained in:
Harrison Deng 2022-04-18 17:49:16 -05:00
parent 677a98549f
commit b1563097cd
8 changed files with 30 additions and 45 deletions

View File

@ -1,11 +1,4 @@
// TODO: basic playlist display.
// TODO: Demo functions.
// TODO: Detect annotated elements.
// TODO: Create getting started.
import * as mappings from "./mapping/mappings.js";
import * as mappings from "./mappings/mappings.js";
import * as player from "./player/player.js";
import * as visualization from "./visualization/visualization.js";
import * as support from "./support/support.js";

View File

@ -11,7 +11,7 @@ import VisUpdateRouter from "../visualization/VisUpdateRouter.js";
* @param {number} value The new numerical value to update to.
*/
// FIXME: Warnings about interpolator not being defined are broken. Docs generate fine.
// 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.

View File

@ -14,7 +14,6 @@ import MusicPlaylist from "./MusicPlaylist.js";
export default class VisMusicPlayer extends MusicPlayer {
#fftSize = 1024;
#visUpdateRouter;
#visUpdateRouterListeners = null;
/**
* Instantiates a music player with visualization features.
@ -30,8 +29,10 @@ export default class VisMusicPlayer extends MusicPlayer {
}
#onMusicChange = () => {
this.#visUpdateRouterListeners = this.#visUpdateRouter.retrieveListeners();
this.#visUpdateRouter?.unbindVisualizer();
const visUpdateRouterListeners = this.#visUpdateRouter.retrieveListeners();
this.#visUpdateRouter.unbindVisualizer();
this.#visUpdateRouter = new VisUpdateRouter(this.currentMusicVisualizer);
this.#visUpdateRouter.loadListeners(visUpdateRouterListeners);
};
/**
@ -40,10 +41,10 @@ export default class VisMusicPlayer extends MusicPlayer {
set playlist(playlist) {
if (!this.playlist) {
super.playlist = playlist;
return; // HACK: If it's the first time, then wait until super() is done.
return; // If it's the first time, then wait until super() is done.
}
this.playlist?.removePositionChangeListener(this.#onMusicChange);
this.playlist.addPositionChangeListener(this.#onMusicChange);
playlist.addPositionChangeListener(this.#onMusicChange);
super.playlist = playlist;
}
@ -52,12 +53,8 @@ export default class VisMusicPlayer extends MusicPlayer {
}
playCurrent() {
console.log("attempted play from vis");
super.playCurrent();
const visualizer = this.playlist.currentMusic.fetchVisualizer();
this.#visUpdateRouter.visualizer = visualizer;
visualizer.analyze();
if (this.#visUpdateRouterListeners) this.#visUpdateRouter.loadListeners(this.#visUpdateRouterListeners);
this.currentMusicVisualizer.analyze();
}

View File

@ -1,5 +1,7 @@
/**@module */
import Visualizer from "./Visualizer.js";
/**
* @callback visualizerBinUpdateListener
* @param {number} timeDelta elapsed time since last update.
@ -29,17 +31,18 @@ export default class VisUpdateRouter {
/**
*
* @param {number} fftSize the fft window size of the visualizer this manager obtains data from.
* @param {Visualizer} visualizer the fft window size of the visualizer this manager obtains data from.
*/
constructor(fftSize) {
constructor(visualizer) {
this.#binnedListeners = [];
this.#rangedListeners = [];
const bins = fftSize / 2; // TODO: Clean this up.
const bins = visualizer.numberOfBins; // TODO: Clean this up.
for (let i = 0; i < bins; i++) {
this.#binnedListeners.push([]);
}
this.#lastBins = new Uint8Array(this.#binnedListeners.length);
this.#visualizer = visualizer;
this.#visualizer.addUpdateListener(this.#visualizerListener);
}
#visualizerListener = (delta, bins) => {
@ -64,16 +67,6 @@ export default class VisUpdateRouter {
}
};
/**
* Sets the current visualizer.
*/
set visualizer(visualizer) {
console.log("vis update router visualizer set.");
if (this.#visualizer) this.unbindVisualizer();
this.#visualizer = visualizer;
visualizer.addUpdateListener(this.#visualizerListener);
}
/**
* Adds a listener to a specific frequency bin.

View File

@ -1,5 +1,3 @@
/**@module */
/**
* @callback visualizerUpdateListener
* @param {number} delta elapsed time since last update.
@ -10,40 +8,43 @@
* Provides a simplified access point to the frequency bins in the form of a visualization update listener.
*/
export default class Visualizer {
#source;
#stream;
#analyzing = false;
#updateListeners = [];
#audioCtx;
#source;
#analyzer;
#buffer;
#lastUpdate;
#fftSize;
/**
*
* @param {MediaSource|HTMLMediaElement} mediaSource a media source to analyze.
* @param {MediaSource|HTMLMediaElement} stream a media source to analyze.
* @param {number} [fftSize = 1024] the size of the fft window.
*/
constructor(mediaSource, fftSize = 1024) {
this.#stream = mediaSource;
constructor(stream, fftSize = 1024) {
this.#fftSize = fftSize;
this.#stream = stream;
this.#analyzing = false;
this.#updateListeners = [];
this.#lastUpdate = null;
}
#initialize() {
this.#audioCtx = new window.AudioContext();
if (mediaSource instanceof HTMLMediaElement) {
if (this.#stream instanceof HTMLMediaElement) {
this.#source = this.#audioCtx.createMediaElementSource(this.#stream);
} else {
this.#source = this.#audioCtx.createMediaStreamSource(this.#stream);
}
this.#analyzer = this.#audioCtx.createAnalyser();
this.#analyzer.fftSize = fftSize;
this.#analyzer.fftSize = this.fftSize;
this.#buffer = new Uint8Array(this.#analyzer.frequencyBinCount);
this.#source.connect(this.#analyzer);
this.#analyzer.connect(this.#audioCtx.destination);
this.#lastUpdate = null;
}
/**
* Begins analyzing and sending out update pings.
*/
@ -51,6 +52,7 @@ export default class Visualizer {
if (this.#analyzing) {
return;
}
if (!this.#audioCtx) this.#initialize();
this.#analyzing = true;
let self = this; // since calling from requestAnimationFrame means "this" is no longer set to produced object.
const update = (timestamp) => {
@ -115,6 +117,6 @@ export default class Visualizer {
* @returns {number} The fft window size.
*/
get fftSize() {
return this.#analyzer.fftSize;
return this.#fftSize;
}
}