//@ts-check import JadefinIntegrity from '../JadefinIntegrity.js'; import Jadefin from "../Jadefin.js"; import JadefinMod from "../JadefinMod.js"; import JadefinModules from "../JadefinModules.js"; import JadefinUtils from "../JadefinUtils.js"; export default JadefinIntegrity("VolumeBoost", import.meta.url, () => new (class VolumeBoost extends JadefinMod { audioCtx = new AudioContext(); audioBypass = this.audioCtx.createGain(); audioGain = this.audioCtx.createGain(); audioComp = this.audioCtx.createDynamicsCompressor(); audioCompGain = this.audioCtx.createGain(); _currentGain = 1; constructor() { super(); this.audioBypass.gain.value = 1; this.audioGain.gain.value = 0; this.audioComp.knee.value = 40; this.audioComp.ratio.value = 12; this.audioComp.attack.value = 0; this.audioComp.release.value = 0.25; this.audioCompGain.gain.value = 0; this.audioBypass.connect(this.audioCtx.destination); this.audioGain.connect(this.audioComp).connect(this.audioCompGain).connect(this.audioCtx.destination); document.addEventListener("click", e => this.audioCtxResume(), true); } get currentGain() { return this._currentGain; } set currentGain(value) { this.log.i(`Changing gain to ${value}`); const diff = Math.abs(this._currentGain - value); const timeNow = this.audioCtx.currentTime; const time = this.audioCtx.currentTime + Math.min(0.5 * diff, 2); if (diff != 0) { this.audioBypass.gain.setValueAtTime(this.audioBypass.gain.value, timeNow); this.audioGain.gain.setValueAtTime(this.audioGain.gain.value, timeNow); this.audioCompGain.gain.setValueAtTime(this.audioCompGain.gain.value, timeNow); this.audioBypass.gain.linearRampToValueAtTime((value <= 1) ? value : 0, time); this.audioGain.gain.linearRampToValueAtTime((value <= 1) ? 0 : value, time); this.audioCompGain.gain.linearRampToValueAtTime((value <= 1) ? 0 : 1, time); } this._currentGain = value; this.connect(); } async init(name, url) { await super.init(name, url); const ExtrasMenu = /** @type {import("./ExtrasMenu.js").default} */ (Jadefin.getMod("ExtrasMenu")); ExtrasMenu.items.push({ name: "Volume Boost", in: ExtrasMenu.IN_CUSTOM, inCustom: (current, item) => { item.asideText = `${this.currentGain}x`; return (current & (ExtrasMenu.IN_PLAYBACKSETTINGS)) == current; }, cb: async (positionTo) => { JadefinModules.actionSheet.show({ positionTo, items: [ {id: "1", name: "1x", selected: this.currentGain == 1}, {id: "2", name: "2x", selected: this.currentGain == 2}, {id: "3", name: "3x", selected: this.currentGain == 3}, {id: "4", name: "4x", selected: this.currentGain == 4}, ] }).then(id => { if (!id) { return; } this.currentGain = parseInt(id); }); } }); document.addEventListener("viewshow", () => { if (JadefinUtils.routePathIsVideo) { this.log.i("Navigating to video"); this.audioCtxResume(); if (this._connectRepeat) { clearInterval(this._connectRepeat); } clearInterval(this._connectRepeat); this._connectRepeat = setInterval(() => this.connect(), 100); } }); this.log.i("Ready"); } connect() { const video = JadefinUtils.video; if (!video) { return; } const last = this.video; const lastSrc = this.videoSrc; if (video != last) { lastSrc?.disconnect(); this.videoSrc = null; } this.video = video; if (!this.videoSrc) { this.log.i("Connected to video element"); this.log.dir(this.video); this.videoSrc = this.audioCtx.createMediaElementSource(this.video); this.videoSrc.connect(this.audioBypass); this.videoSrc.connect(this.audioGain); } if (this._connectRepeat) { clearInterval(this._connectRepeat); } } audioCtxResume() { if (this.audioCtx.state === "suspended") { this.audioCtx.resume(); } } })());