Files
Phoenix/scripts/test_rta_profile.mjs

122 lines
4.9 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import vm from 'node:vm';
import { getRtwCenters } from '../www/core/rtw_centers.js';
import { buildRtwTickPositions, selectLocalRtwPacket } from '../www/views/realtime.js';
const source = fs.readFileSync(new URL('../www/core/audio.js', import.meta.url), 'utf8');
const configSource = fs.readFileSync(new URL('../www/core/config.js', import.meta.url), 'utf8');
const correlationNormalizerSource = configSource.match(
/export function normalizeCorrelationResponseSeconds[\s\S]*?\n\}/,
)?.[0];
assert.ok(correlationNormalizerSource, 'correlation response normalization must remain testable');
const correlationContext = vm.createContext({ Number });
vm.runInContext(
correlationNormalizerSource.replace('export function', 'function'),
correlationContext,
);
assert.equal(correlationContext.normalizeCorrelationResponseSeconds(0.5), 0.5);
assert.equal(correlationContext.normalizeCorrelationResponseSeconds(1.0), 1.0);
assert.equal(correlationContext.normalizeCorrelationResponseSeconds(2.5), 2.5);
assert.equal(correlationContext.normalizeCorrelationResponseSeconds(Number.NaN), 1.0);
const functionSource = source.match(/export function buildRtaRuntimeConfig[\s\S]*?\n\}/)?.[0];
assert.ok(functionSource, 'buildRtaRuntimeConfig must remain testable');
const context = vm.createContext({
Number,
normalizeCorrelationResponseSeconds: correlationContext.normalizeCorrelationResponseSeconds,
getRtwCenters(mode) {
if (mode === '1_12') return new Array(121).fill(0);
if (mode === '1_6') return new Array(61).fill(0);
return new Array(31).fill(0);
},
});
vm.runInContext(functionSource.replace('export function', 'function'), context);
const forced = context.buildRtaRuntimeConfig({
RTA_BAR_LAYOUT: 'rtw',
RTA_ENGINE: 'fft',
RTA_BPO_MODE: '1_12',
RTA_FREQ_RANGE: 'lf',
RTA_IIR_ORDER: 2,
RTA_DETECTOR: 'peak',
RTA_PEAK_HOLD_MODE: 'fall',
RTA_PEAK_HOLD_SEC: 4,
RTA_PEAK_DECAY_DB_PER_S: 20,
RTA_PEAK_RESET_TOKEN: 9,
CORR_RESPONSE_S: 2.5,
CORR_SILENCE_THRESHOLD_RMS_DBFS: -50,
CORR_RESET_TOKEN: 7,
XY_POINTS: 256,
});
assert.equal(forced.engine, 'iir');
assert.equal(forced.bpo, '1_12');
assert.equal(forced.freqRange, 'norm');
assert.equal(forced.order, 6);
assert.equal(forced.detector, 'peak');
assert.equal(forced.rtaPeakHoldMode, 'fall');
assert.equal(forced.rtaPeakHoldSeconds, 4);
assert.equal(forced.rtaPeakDecayDbPerSecond, 20);
assert.equal(forced.rtaPeakResetToken, 9);
assert.equal(forced.tauFast, 0.125);
assert.equal(forced.rtwCenters.length, 121);
assert.equal(forced.correlationResponseS, 2.5);
assert.equal(forced.correlationSilenceThresholdRmsDbfs, -50);
assert.equal(forced.correlationResetToken, 7);
assert.equal(forced.xyPoints, 256);
const veryFastCorrelation = context.buildRtaRuntimeConfig({ CORR_RESPONSE_S: 0.5 });
assert.equal(veryFastCorrelation.correlationResponseS, 0.5);
const extension = context.buildRtaRuntimeConfig({
RTA_BAR_LAYOUT: 'iec',
RTA_ENGINE: 'fft',
RTA_BPO_MODE: '1_12',
RTA_FREQ_RANGE: 'lf',
RTA_IIR_ORDER: 8,
});
assert.equal(extension.engine, 'fft');
assert.equal(extension.bpo, '1_12');
assert.equal(extension.freqRange, 'lf');
assert.equal(extension.order, 8);
const selectionSource = configSource.match(/function applyRtaBpoSelection[\s\S]*?\n\}/)?.[0];
assert.ok(selectionSource, 'RTA BPO selection policy must remain testable');
const selectionContext = vm.createContext({
String,
CONFIG: { RTA_BPO_MODE: '1_3', RTA_BAR_LAYOUT: 'rtw' },
});
vm.runInContext(selectionSource, selectionContext);
assert.equal(selectionContext.applyRtaBpoSelection('1_6'), '1_6');
assert.equal(selectionContext.CONFIG.RTA_BPO_MODE, '1_6');
assert.equal(selectionContext.CONFIG.RTA_BAR_LAYOUT, 'rtw');
assert.equal(selectionContext.applyRtaBpoSelection('1_3'), '1_3');
assert.equal(selectionContext.CONFIG.RTA_BAR_LAYOUT, 'rtw');
const twelfthCenters = getRtwCenters('1_12');
const staleTwelfthPacket = {
engine: 'iir',
bpo: '1_12',
centers: twelfthCenters,
bands_avg: twelfthCenters.map((_, index) => index),
bands_peak: twelfthCenters.map((_, index) => index + 1000),
};
const selectedSixth = selectLocalRtwPacket(staleTwelfthPacket, '1_6');
assert.equal(selectedSixth.bpo, '1_6');
assert.equal(selectedSixth.centers.length, getRtwCenters('1_6').length);
assert.equal(selectedSixth.bands_avg.length, selectedSixth.centers.length);
assert.equal(selectedSixth.bands_peak.length, selectedSixth.centers.length);
for (const mode of ['1_3', '1_6', '1_12']) {
const centers = getRtwCenters(mode);
const ticks = [20, 31.5, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
const positions = buildRtwTickPositions(centers, ticks);
for (const tick of ticks) {
const index = centers.indexOf(tick);
assert.ok(index >= 0, `${mode} must contain the ${tick} Hz display band`);
assert.equal(positions[String(tick)], (index + 0.5) / centers.length);
}
}
console.log('RTA profile regression tests passed');