iOS 1.0 RC 1: battery and heat work, version label, web player redraw tweaks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0fc35b13e8
commit
c0e33b5e3e
18 files changed
+143
-36
No files matched your search
+28
-10
@@ -102,12 +102,17 @@ const Wave = {
|
||||
return;
|
||||
}
|
||||
const names = Object.keys(this.peaks), n = this.peaks[names[0]].length;
|
||||
const full = new Float32Array(n), mixed = new Float32Array(n);
|
||||
for (const nm of names) {
|
||||
const g = stemGain(nm, names);
|
||||
this.peaks[nm].forEach((p, i) => { const v = p / 1000; full[i] += v * v; mixed[i] += v * v * g * g; });
|
||||
// The envelope only changes with the song or the mix, not every redraw.
|
||||
const gains = names.map(nm => stemGain(nm, names)), gk = gains.join();
|
||||
if (this.env?.peaks !== this.peaks || this.env.gk !== gk) {
|
||||
const full = new Float32Array(n), mixed = new Float32Array(n);
|
||||
names.forEach((nm, k) => {
|
||||
const g = gains[k];
|
||||
this.peaks[nm].forEach((p, i) => { const v = p / 1000; full[i] += v * v; mixed[i] += v * v * g * g; });
|
||||
});
|
||||
this.env = { peaks: this.peaks, gk, full, mixed, max: Math.sqrt(Math.max(...full)) || 1 };
|
||||
}
|
||||
const max = Math.sqrt(Math.max(...full)) || 1;
|
||||
const { full, mixed, max } = this.env;
|
||||
const bars = Math.max(20, Math.floor(w / 3)), bw = w / bars;
|
||||
for (let b = 0; b < bars; b++) {
|
||||
const i = Math.floor(b / bars * n);
|
||||
@@ -117,6 +122,15 @@ const Wave = {
|
||||
x.fillStyle = b / bars < frac ? this.c.accent : this.c.bar; x.fillRect(b * bw, (h - bh) / 2, bw - 1, bh);
|
||||
}
|
||||
},
|
||||
// Redraws during playback only when the played part has grown by a bar (or a pixel without peaks).
|
||||
follow() {
|
||||
const w = this.canvas.clientWidth, dur = E.duration();
|
||||
const steps = this.peaks ? Math.max(20, Math.floor(w / 3)) : w;
|
||||
const at = dur ? Math.floor(Math.min(1, E.position() / dur) * steps) : 0;
|
||||
if (at === this.at) return;
|
||||
this.at = at;
|
||||
this.draw();
|
||||
},
|
||||
};
|
||||
{
|
||||
let drag = false;
|
||||
@@ -387,10 +401,14 @@ document.addEventListener("keydown", ev => {
|
||||
else if (k === "]" || k === "[") { const i = SPEEDS.indexOf(S.speed) + (k === "]" ? 1 : -1); if (SPEEDS[i]) setSpeed(SPEEDS[i]); }
|
||||
});
|
||||
|
||||
(function frame() {
|
||||
if (E.playing && !E.loading) { $("#t-pos").textContent = fmtTime(E.position()); Wave.draw(); tickLyrics(); }
|
||||
requestAnimationFrame(frame);
|
||||
})();
|
||||
// The clock, waveform and lyrics follow playback 5 times a second instead of every frame:
|
||||
// none of them change faster than that, and a 120 Hz loop keeps phones warm.
|
||||
setInterval(() => {
|
||||
if (document.hidden || !E.playing || E.loading) return;
|
||||
const t = fmtTime(E.position()), el = $("#t-pos");
|
||||
if (el.textContent !== t) el.textContent = t;
|
||||
Wave.follow(); tickLyrics();
|
||||
}, 200);
|
||||
setInterval(() => { if (E.playing) { UI.progress(); saveQueue(); } }, 5000);
|
||||
|
||||
on("track", () => { UI.track(); UI.transport(); UI.progress(); Wave.load(Q.cur()); marks(); if (drawer) UI.drawer(); });
|
||||
@@ -1154,5 +1172,5 @@ async function connect() {
|
||||
UI.all();
|
||||
route();
|
||||
Live.poll();
|
||||
setInterval(() => Stems.refresh(), 5 * 60 * 1000);
|
||||
setInterval(() => { if (!document.hidden) Stems.refresh(); }, 5 * 60 * 1000);
|
||||
})();
|
||||
Reference in new issue
Block a user