Merge p10-remove-ts-smoothing into dev (drop client-side datum smoothing; waveform smoothing stays the server's job)
This commit is contained in:
@@ -263,9 +263,8 @@ const BLOB_RESTITUTION_SOFT = 0.05; // residual restitution at strength = 0 (al
|
||||
* the soft end → elastic reflection of the inward velocity at the hard end. The waveform
|
||||
* is read-only authority: it pushes the fluid, the fluid never moves it.
|
||||
*/
|
||||
// Phase 10 collision retune (Daniel: "less explosive, more bouncy", no jitter, no stuck wax). The
|
||||
// smoothed waveform (item 1) gives a gently-moving boundary, so the response can be springier without
|
||||
// buzzing. Restitution is now SUB-unity: a real bounce conserves-or-loses energy, never adds it —
|
||||
// Phase 10 collision retune (Daniel: "less explosive, more bouncy", no jitter, no stuck wax).
|
||||
// Restitution is now SUB-unity: a real bounce conserves-or-loses energy, never adds it —
|
||||
// over-unity (the old 1.1) injected energy each contact and read as "explosive". 0.85 at the hard end
|
||||
// is lively/springy; the soft end stays near-zero (mush).
|
||||
const WAVE_COLLIDE_SPRING = 10.0; // soft penalty stiffness pushing wax off the ribbon (slightly softer)
|
||||
@@ -550,43 +549,6 @@ function decodeSamples(base64: string): Uint8Array {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Envelope-follower smoothing time constant, seconds — mirrors C#
|
||||
* RmsLoudnessAlgorithm.SmoothingTimeConstantSeconds. The ~50 ms target rounds the spikey
|
||||
* per-sample loudness into a smooth ribbon contour (Phase 10 tuning).
|
||||
*/
|
||||
const SMOOTHING_TIME_CONSTANT_SECONDS = 0.05;
|
||||
|
||||
/**
|
||||
* Smooth the [0,255] loudness datum in place with a symmetric (zero-phase) one-pole envelope
|
||||
* follower targeting SMOOTHING_TIME_CONSTANT_SECONDS. This runs at DECODE time so EXISTING stored
|
||||
* mixes — whose vault profiles predate the C#-side preprocessing smoothing — read as a smooth
|
||||
* curve with no data regeneration. New mixes are already smoothed at preprocessing; a second light
|
||||
* pass over an already-smooth curve is near-idempotent, so applying it unconditionally here is safe.
|
||||
*
|
||||
* The coefficient a = exp(−secondsPerSample / τ): forward then backward pass cancels the single-pole
|
||||
* lag (no time shift). Bytes stay [0,255]; we smooth in float and round back. A degenerate sample
|
||||
* rate (≤0 or non-finite) leaves the data untouched.
|
||||
*/
|
||||
function smoothDatum(samples: Uint8Array, sampleCount: number, durationSeconds: number): void {
|
||||
if (sampleCount < 2 || durationSeconds <= 0 || !Number.isFinite(durationSeconds)) return;
|
||||
const secondsPerSample = durationSeconds / sampleCount;
|
||||
const a = Math.exp(-secondsPerSample / SMOOTHING_TIME_CONSTANT_SECONDS);
|
||||
|
||||
// Float working buffer over the real samples (tail padding, if any, is untouched).
|
||||
const env = new Float32Array(sampleCount);
|
||||
let acc = samples[0];
|
||||
for (let i = 0; i < sampleCount; i++) {
|
||||
acc = a * acc + (1 - a) * samples[i];
|
||||
env[i] = acc;
|
||||
}
|
||||
acc = env[sampleCount - 1];
|
||||
for (let i = sampleCount - 1; i >= 0; i--) {
|
||||
acc = a * acc + (1 - a) * env[i];
|
||||
samples[i] = Math.round(Math.min(255, Math.max(0, acc)));
|
||||
}
|
||||
}
|
||||
|
||||
// ── Shaders. ─────────────────────────────────────────────────────────────────────
|
||||
//
|
||||
// Vertex: trivial pass-through. We draw a single triangle that more than covers the
|
||||
@@ -2026,11 +1988,6 @@ export function create(canvas: HTMLCanvasElement): MixVisualizerHandle {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Smooth the loudness contour at decode time so EXISTING mixes (stored before the C#-side
|
||||
// preprocessing smoothing) read as a smooth curve with no regeneration. Mutates `samples` in
|
||||
// place — both the GPU texture (below) and the CPU collision mirror (datum.samples) read it.
|
||||
smoothDatum(samples, sampleCount, durationSeconds);
|
||||
|
||||
// Width = min(N, a safe power-of-two cap). The power-of-two cap (4096) is well
|
||||
// under every real GL_MAX_TEXTURE_SIZE and keeps row arithmetic clean; we
|
||||
// still clamp it to the actual max in case a driver reports something smaller.
|
||||
|
||||
Reference in New Issue
Block a user