Restore smooth realtime fall ballistics
This commit is contained in:
+10
-29
@@ -200,10 +200,13 @@ export async function render(env, state) {
|
||||
} else {
|
||||
const integrated = baseLevels;
|
||||
const displayBase = applyDisplayHold(state, integrated, CONFIG, range);
|
||||
// Native IIR values already contain the selected power-domain
|
||||
// integration. A second browser attack/hold stage would falsify it.
|
||||
const display = displayBase;
|
||||
syncNativePeakHold(state, displayRtaPacket, CONFIG, range, state.mapping.length, 'iir');
|
||||
// Detector integration remains authoritative in the native DSP. The
|
||||
// display-only hold/release stages advance on every VSync so repeated
|
||||
// transport anchors cannot freeze a falling bar or peak hairline.
|
||||
const display = (CONFIG.REALTIME_RENDER_STYLE || 'bars') === 'bars'
|
||||
? applyRealtimeBarBallistics(state, displayBase, CONFIG, range)
|
||||
: displayBase;
|
||||
applyPeakHold(state, integrated, CONFIG, range);
|
||||
state.displayLevels = display;
|
||||
state.currentRange = range;
|
||||
if (typeof window !== 'undefined') window.__RTA_STATE__ = state;
|
||||
@@ -237,7 +240,7 @@ export async function render(env, state) {
|
||||
const display = (CONFIG.REALTIME_RENDER_STYLE || 'bars') === 'bars'
|
||||
? applyRealtimeBarBallistics(state, displayBase, CONFIG, range)
|
||||
: displayBase;
|
||||
syncNativePeakHold(state, displayRtaPacket, CONFIG, range, state.mapping.length, 'fft');
|
||||
applyPeakHold(state, integrated, CONFIG, range);
|
||||
state.displayLevels = display;
|
||||
state.currentRange = range;
|
||||
if (typeof window !== 'undefined') window.__RTA_STATE__ = state;
|
||||
@@ -439,7 +442,7 @@ function applyIntegration(state, levels, CONFIG, range) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function applyPeakHold(state, levels, CONFIG, range) {
|
||||
export function applyPeakHold(state, levels, CONFIG, range) {
|
||||
const mode = CONFIG.RTA_PEAK_HOLD_MODE || 'fall';
|
||||
const len = levels.length;
|
||||
const mapped = PEAK_HOLD_MAP.get(mode);
|
||||
@@ -482,28 +485,6 @@ function applyPeakHold(state, levels, CONFIG, range) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function syncNativePeakHold(state, packet, CONFIG, range, expectedLen, engine) {
|
||||
const src = isVectorLike(packet?.bands_peak) && packet.bands_peak.length === expectedLen
|
||||
? packet.bands_peak
|
||||
: null;
|
||||
if (!src) return applyPeakHold(state, state.displayLevels, CONFIG, range);
|
||||
const gain = engine === 'iir'
|
||||
? (Number(CONFIG.RTA_DISPLAY_GAIN_IIR_DB ?? 0) || 0)
|
||||
: (Number(CONFIG.RTA_DISPLAY_GAIN_FFT_DB ?? 0) || 0);
|
||||
if (!state.peakHold || state.peakHold.length !== expectedLen) {
|
||||
state.peakHold = new Float32Array(expectedLen);
|
||||
}
|
||||
for (let i = 0; i < expectedLen; i++) {
|
||||
const value = Number(src[i]);
|
||||
state.peakHold[i] = clamp(
|
||||
(Number.isFinite(value) ? value : range.bottom) + gain,
|
||||
range.bottom,
|
||||
range.top,
|
||||
);
|
||||
}
|
||||
return state.peakHold;
|
||||
}
|
||||
|
||||
function applyDisplayHold(state, levels, CONFIG, range) {
|
||||
const holdSec = Math.max(0, Number(CONFIG.RTA_DISPLAY_HOLD_SEC) || 0);
|
||||
const len = levels.length;
|
||||
@@ -538,7 +519,7 @@ function applyDisplayHold(state, levels, CONFIG, range) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function applyRealtimeBarBallistics(state, levels, CONFIG, range) {
|
||||
export function applyRealtimeBarBallistics(state, levels, CONFIG, range) {
|
||||
const holdMs = Math.max(0, Number(CONFIG.REALTIME_BAR_HOLD_MS) || 0);
|
||||
const decayRate = Math.max(0, Number(CONFIG.REALTIME_BAR_DECAY_DB_PER_S) || 0);
|
||||
const len = levels.length;
|
||||
|
||||
Reference in New Issue
Block a user