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. import * as mappings from "./mappings/mappings.js";
// TODO: Demo functions.
// TODO: Detect annotated elements.
// TODO: Create getting started.
import * as mappings from "./mapping/mappings.js";
import * as player from "./player/player.js"; import * as player from "./player/player.js";
import * as visualization from "./visualization/visualization.js"; import * as visualization from "./visualization/visualization.js";
import * as support from "./support/support.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. * @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. * 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 { export default class VisMusicPlayer extends MusicPlayer {
#fftSize = 1024; #fftSize = 1024;
#visUpdateRouter; #visUpdateRouter;
#visUpdateRouterListeners = null;
/** /**
* Instantiates a music player with visualization features. * Instantiates a music player with visualization features.
@ -30,8 +29,10 @@ export default class VisMusicPlayer extends MusicPlayer {
} }
#onMusicChange = () => { #onMusicChange = () => {
this.#visUpdateRouterListeners = this.#visUpdateRouter.retrieveListeners(); const visUpdateRouterListeners = this.#visUpdateRouter.retrieveListeners();
this.#visUpdateRouter?.unbindVisualizer(); 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) { set playlist(playlist) {
if (!this.playlist) { if (!this.playlist) {
super.playlist = 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?.removePositionChangeListener(this.#onMusicChange);
this.playlist.addPositionChangeListener(this.#onMusicChange); playlist.addPositionChangeListener(this.#onMusicChange);
super.playlist = playlist; super.playlist = playlist;
} }
@ -52,12 +53,8 @@ export default class VisMusicPlayer extends MusicPlayer {
} }
playCurrent() { playCurrent() {
console.log("attempted play from vis");
super.playCurrent(); super.playCurrent();
const visualizer = this.playlist.currentMusic.fetchVisualizer(); this.currentMusicVisualizer.analyze();
this.#visUpdateRouter.visualizer = visualizer;
visualizer.analyze();
if (this.#visUpdateRouterListeners) this.#visUpdateRouter.loadListeners(this.#visUpdateRouterListeners);
} }

View File

@ -1,5 +1,7 @@
/**@module */ /**@module */
import Visualizer from "./Visualizer.js";
/** /**
* @callback visualizerBinUpdateListener * @callback visualizerBinUpdateListener
* @param {number} timeDelta elapsed time since last update. * @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.#binnedListeners = [];
this.#rangedListeners = []; 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++) { for (let i = 0; i < bins; i++) {
this.#binnedListeners.push([]); this.#binnedListeners.push([]);
} }
this.#lastBins = new Uint8Array(this.#binnedListeners.length); this.#lastBins = new Uint8Array(this.#binnedListeners.length);
this.#visualizer = visualizer;
this.#visualizer.addUpdateListener(this.#visualizerListener);
} }
#visualizerListener = (delta, bins) => { #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. * Adds a listener to a specific frequency bin.

View File

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