UNPKG

@omnimedia/omnitool

Version:

open source video processing tools

93 lines 2.89 kB
import { measureAudioLevel } from '../../parts/audio-level.js'; export class AudioLevels { context; time; isPlaying; #meters = new Set(); #items = new Map(); #frame = null; #running = false; constructor(context, time, isPlaying) { this.context = context; this.time = time; this.isPlaying = isPlaying; } on(items, listener) { const silent = this.context.createGain(); const analyser = this.context.createAnalyser(); silent.gain.value = 0; analyser.smoothingTimeConstant = 0; analyser.connect(silent); silent.connect(this.context.destination); const meter = { items, silent, listener, analyser, nodes: new Set(), samples: new Float32Array(analyser.fftSize) }; this.#meters.add(meter); if (this.isPlaying()) this.start(); return () => { if (!this.#meters.delete(meter)) return; for (const node of meter.nodes) node.disconnect(analyser); analyser.disconnect(); silent.disconnect(); if (!this.#meters.size) this.stop(); }; } attach(itemId, node) { this.#items.set(node, itemId); } detach(node) { this.#items.delete(node); for (const meter of this.#meters) { if (meter.nodes.delete(node)) node.disconnect(meter.analyser); } } start() { if (this.#running || !this.#meters.size) return; this.#running = true; this.#frame = requestAnimationFrame(() => this.#tick()); } stop() { this.#running = false; if (this.#frame !== null) cancelAnimationFrame(this.#frame); this.#frame = null; } #tick() { if (!this.#running) return; for (const meter of this.#meters) { this.#sync(meter); meter.analyser.getFloatTimeDomainData(meter.samples); meter.listener({ time: this.time(), ...measureAudioLevel(meter.samples) }); } if (this.#running) this.#frame = requestAnimationFrame(() => this.#tick()); } #sync(meter) { const selected = new Set(meter.items()); for (const [node, itemId] of this.#items) { const connected = meter.nodes.has(node); const shouldConnect = selected.has(itemId); if (shouldConnect && !connected) { node.connect(meter.analyser); meter.nodes.add(node); } else if (!shouldConnect && connected) { node.disconnect(meter.analyser); meter.nodes.delete(node); } } } } //# sourceMappingURL=audio-levels.js.map