mirror of
https://github.com/radio95-rnt/RadioPlayer.git
synced 2026-07-29 15:29:14 +02:00
smooth
This commit is contained in:
+55
-14
@@ -165,6 +165,32 @@
|
|||||||
let histInput = new Array(MAX_PTS).fill(null);
|
let histInput = new Array(MAX_PTS).fill(null);
|
||||||
let histAudio = new Array(MAX_PTS).fill(null);
|
let histAudio = new Array(MAX_PTS).fill(null);
|
||||||
let histAgc = new Array(MAX_PTS).fill(null);
|
let histAgc = new Array(MAX_PTS).fill(null);
|
||||||
|
let dispInput = new Array(MAX_PTS).fill(null);
|
||||||
|
let dispAudio = new Array(MAX_PTS).fill(null);
|
||||||
|
let dispAgc = new Array(MAX_PTS).fill(null);
|
||||||
|
|
||||||
|
const LERP = 0.15; // 0.0 = never moves, 1.0 = instant jump
|
||||||
|
|
||||||
|
function lerp(a, b) {
|
||||||
|
if (a === null) return b;
|
||||||
|
if (b === null) return a;
|
||||||
|
return a + (b - a) * LERP;
|
||||||
|
}
|
||||||
|
|
||||||
|
function animLoop() {
|
||||||
|
let dirty = false;
|
||||||
|
for (let i = 0; i < MAX_PTS; i++) {
|
||||||
|
const ni = lerp(dispInput[i], histInput[i]);
|
||||||
|
const na = lerp(dispAudio[i], histAudio[i]);
|
||||||
|
const ng = lerp(dispAgc[i], histAgc[i]);
|
||||||
|
if (ni !== dispInput[i] || na !== dispAudio[i] || ng !== dispAgc[i]) dirty = true;
|
||||||
|
dispInput[i] = ni;
|
||||||
|
dispAudio[i] = na;
|
||||||
|
dispAgc[i] = ng;
|
||||||
|
}
|
||||||
|
if (dirty) drawScope();
|
||||||
|
requestAnimationFrame(animLoop);
|
||||||
|
}
|
||||||
|
|
||||||
const canvas = document.getElementById('scope');
|
const canvas = document.getElementById('scope');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
@@ -233,29 +259,44 @@
|
|||||||
|
|
||||||
// draw series
|
// draw series
|
||||||
function drawLine(hist, color) {
|
function drawLine(hist, color) {
|
||||||
const slice = hist.slice(-nPts);
|
const slice = hist.slice(-nPts).filter((v, i, a) => {
|
||||||
const step = W / (nPts - 1);
|
// fill nulls with neighbors for smoother rendering
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
const pts = slice.map((v, i) => ({ x: i * (W / (nPts - 1)), y: v === null ? null : toY(v) }));
|
||||||
|
|
||||||
ctx.strokeStyle = color;
|
ctx.strokeStyle = color;
|
||||||
ctx.lineWidth = 1.5;
|
ctx.lineWidth = 1.5;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
let started = false;
|
let started = false;
|
||||||
for (let i = 0; i < slice.length; i++) {
|
|
||||||
if (slice[i] === null) { started = false; continue; }
|
for (let i = 0; i < pts.length; i++) {
|
||||||
const x = i * step;
|
if (pts[i].y === null) { started = false; continue; }
|
||||||
const y = toY(slice[i]);
|
if (!started) { ctx.moveTo(pts[i].x, pts[i].y); started = true; continue; }
|
||||||
if (!started) { ctx.moveTo(x, y); started = true; }
|
|
||||||
else ctx.lineTo(x, y);
|
// cardinal spline control points
|
||||||
|
const p0 = pts[i - 2]?.y !== null ? pts[i - 2] : pts[i - 1];
|
||||||
|
const p1 = pts[i - 1];
|
||||||
|
const p2 = pts[i];
|
||||||
|
const p3 = pts[i + 1] ?? p2;
|
||||||
|
|
||||||
|
const tension = 0.4;
|
||||||
|
const cp1x = p1.x + (p2.x - p0.x) * tension / 2;
|
||||||
|
const cp1y = p1.y + (p2.y - p0.y) * tension / 2;
|
||||||
|
const cp2x = p2.x - (p3.x - p1.x) * tension / 2;
|
||||||
|
const cp2y = p2.y - (p3.y - p1.y) * tension / 2;
|
||||||
|
|
||||||
|
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, p2.x, p2.y);
|
||||||
}
|
}
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
// glow
|
|
||||||
ctx.strokeStyle = color + '44';
|
ctx.strokeStyle = color + '44';
|
||||||
ctx.lineWidth = 4;
|
ctx.lineWidth = 4;
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawLine(histInput, '#f472b6');
|
drawLine(dispInput, '#f472b6');
|
||||||
drawLine(histAudio, '#38bdf8');
|
drawLine(dispAudio, '#38bdf8');
|
||||||
drawLine(histAgc, '#fb923c');
|
drawLine(dispAgc, '#fb923c');
|
||||||
}
|
}
|
||||||
|
|
||||||
function decode(b64) {
|
function decode(b64) {
|
||||||
@@ -308,7 +349,7 @@
|
|||||||
ws.addEventListener('open', () => {
|
ws.addEventListener('open', () => {
|
||||||
setStatus('connected', 'Connected');
|
setStatus('connected', 'Connected');
|
||||||
poll();
|
poll();
|
||||||
pollTimer = setInterval(poll, 70 + (Math.random() * 30));
|
pollTimer = setInterval(poll, 50 + (Math.random() * 25));
|
||||||
});
|
});
|
||||||
ws.addEventListener('message', e => {
|
ws.addEventListener('message', e => {
|
||||||
try {
|
try {
|
||||||
@@ -326,7 +367,7 @@
|
|||||||
function poll() { if (ws && ws.readyState === WebSocket.OPEN) ws.send(POLL_MSG); }
|
function poll() { if (ws && ws.readyState === WebSocket.OPEN) ws.send(POLL_MSG); }
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
drawScope();
|
animLoop();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user