mirror of
https://github.com/narrrl/pl8list-rewind.git
synced 2026-11-04 16:47:00 +01:00
added volume control to desktop
This commit is contained in:
1 parent
2ddc1b5629
commit
482cfc299b
4 files changed
+80
-4
No files matched your search
+26
-2
@@ -2,7 +2,8 @@
|
||||
// crossfade into each other.
|
||||
//
|
||||
// Where the browser allows it, both <audio> elements run through a Web Audio graph:
|
||||
// a gain per deck (for the crossfade) into one analyser (for the visuals). iOS is
|
||||
// a gain per deck (for the crossfade) into one analyser (for the visuals), then a
|
||||
// master gain for the volume, so the visuals look the same at any volume. iOS is
|
||||
// left out: its element volume is read-only and Web Audio stops when the screen
|
||||
// locks, which would break lock-screen playback. There tracks switch with a cut.
|
||||
|
||||
@@ -12,6 +13,7 @@ import { type Track, streamUrl } from "./api";
|
||||
const CROSSFADE = 0.9; // seconds
|
||||
const PRELOAD_BUFFER = 6; // seconds buffered of the track after the current one
|
||||
const PLAY_BUFFER = 30;
|
||||
const VOLUME_KEY = "pl8inf.volume";
|
||||
|
||||
type Hls = HlsType;
|
||||
type HlsClass = typeof HlsType;
|
||||
@@ -68,6 +70,8 @@ export class Player {
|
||||
private ctx: AudioContext | null = null;
|
||||
private unlocking: Promise<void> | null = null;
|
||||
private fadeEnd = 0;
|
||||
private master: GainNode | null = null;
|
||||
private vol = Number(localStorage.getItem(VOLUME_KEY) ?? 1);
|
||||
private listeners = new Map<PlayerEvent, Set<() => void>>();
|
||||
analyser: AnalyserNode | null = null;
|
||||
/// False on iOS, see the top of this file.
|
||||
@@ -84,6 +88,8 @@ export class Player {
|
||||
return { el, hls: null, gain: null, track: null, wantPlay: false, gen: 0 };
|
||||
};
|
||||
this.decks = [deck(), deck()];
|
||||
if (!(this.vol >= 0 && this.vol <= 1)) this.vol = 1;
|
||||
this.volume = this.vol;
|
||||
for (const d of this.decks) {
|
||||
for (const ev of FORWARDED) {
|
||||
d.el.addEventListener(ev, () => {
|
||||
@@ -150,8 +156,10 @@ export class Player {
|
||||
const analyser = ctx.createAnalyser();
|
||||
analyser.fftSize = 2048;
|
||||
analyser.smoothingTimeConstant = 0.2; // features.ts smooths per feature; this only takes the edge off the FFT
|
||||
analyser.connect(ctx.destination);
|
||||
const master = ctx.createGain();
|
||||
analyser.connect(master).connect(ctx.destination);
|
||||
for (const d of this.decks) {
|
||||
d.el.volume = 1; // the master gain takes over
|
||||
const gain = ctx.createGain();
|
||||
gain.gain.value = d === this.decks[this.cur] ? 1 : 0;
|
||||
ctx.createMediaElementSource(d.el).connect(gain).connect(analyser);
|
||||
@@ -159,6 +167,8 @@ export class Player {
|
||||
}
|
||||
this.ctx = ctx;
|
||||
this.analyser = analyser;
|
||||
this.master = master;
|
||||
this.volume = this.vol;
|
||||
}
|
||||
|
||||
/// Play a track, crossfading from the current one when possible.
|
||||
@@ -282,4 +292,18 @@ export class Player {
|
||||
set muted(m: boolean) {
|
||||
for (const d of this.decks) d.el.muted = m;
|
||||
}
|
||||
|
||||
/// 0 to 1, as the slider shows it. Squared on the way out, so it sounds even.
|
||||
/// Without a graph the element volumes carry it; on iOS they are read-only.
|
||||
get volume(): number {
|
||||
return this.vol;
|
||||
}
|
||||
|
||||
set volume(v: number) {
|
||||
this.vol = Math.max(0, Math.min(1, v));
|
||||
localStorage.setItem(VOLUME_KEY, String(this.vol));
|
||||
const out = this.vol * this.vol;
|
||||
if (this.master) this.master.gain.value = out;
|
||||
else for (const d of this.decks) d.el.volume = out;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user