Correct audio metering and realtime displays
This commit is contained in:
@@ -3,42 +3,17 @@ import fs from 'node:fs';
|
||||
import vm from 'node:vm';
|
||||
|
||||
const source = fs.readFileSync(new URL('../www/views/phase_wheel.js', import.meta.url), 'utf8');
|
||||
const functionSource = source.match(/export function summarizeWeightedPhase[\s\S]*?\n\}/)?.[0];
|
||||
assert.ok(functionSource, 'weighted phase summary must remain testable');
|
||||
const context = vm.createContext({ Number, Math });
|
||||
vm.runInContext(functionSource.replace('export function', 'function'), context);
|
||||
const smoothingSource = source.match(/export function smoothingAlpha[\s\S]*?\n\}/)?.[0];
|
||||
assert.ok(smoothingSource, 'time-based smoothing must remain testable');
|
||||
vm.runInContext(smoothingSource.replace('export function', 'function'), context);
|
||||
|
||||
const dominant = context.summarizeWeightedPhase(
|
||||
new Float32Array([0, Math.PI / 2]),
|
||||
new Float32Array([100, 1]),
|
||||
2,
|
||||
);
|
||||
assert.ok(dominant, 'valid weighted phases must produce a summary');
|
||||
assert.ok(Math.abs(dominant.angle) < 0.02,
|
||||
'a quiet phase component must not pull a dominant component toward an unweighted mean');
|
||||
const oneFrame = context.smoothingAlpha(1 / 60, 0.2);
|
||||
const twoFrames = 1 - Math.pow(1 - oneFrame, 2);
|
||||
assert.ok(Math.abs(twoFrames - context.smoothingAlpha(1 / 30, 0.2)) < 1e-12,
|
||||
'smoothing over equal real time must not depend on the display frame rate');
|
||||
|
||||
const wrapped = context.summarizeWeightedPhase(
|
||||
new Float32Array([179 * Math.PI / 180, -179 * Math.PI / 180]),
|
||||
new Float32Array([1, 1]),
|
||||
2,
|
||||
);
|
||||
assert.ok(Math.abs(Math.abs(wrapped.angle) - Math.PI) < 0.02,
|
||||
'circular averaging must preserve the wrap around at 180 degrees');
|
||||
assert.ok(wrapped.coherence > 0.99,
|
||||
'nearly aligned phase observations must report high coherence');
|
||||
|
||||
const opposed = context.summarizeWeightedPhase(
|
||||
new Float32Array([0, Math.PI]),
|
||||
new Float32Array([1, 1]),
|
||||
2,
|
||||
);
|
||||
assert.ok(opposed.coherence < 1e-6,
|
||||
'opposing phase observations must report that their mean direction is ambiguous');
|
||||
|
||||
assert.equal(context.summarizeWeightedPhase(
|
||||
new Float32Array([0]),
|
||||
new Float32Array([0]),
|
||||
1,
|
||||
), null, 'samples without common L/R energy must not invent a phase angle');
|
||||
assert.doesNotMatch(source, /auto\.gain \* PHASE_AGC_BASE_GAIN/,
|
||||
'AGC target gain must not be multiplied a second time');
|
||||
|
||||
console.log('phase wheel regression tests passed');
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
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 { selectLocalRtwPacket } from '../www/views/realtime.js';
|
||||
|
||||
const source = fs.readFileSync(new URL('../www/core/audio.js', import.meta.url), 'utf8');
|
||||
const functionSource = source.match(/export function buildRtaRuntimeConfig[\s\S]*?\n\}/)?.[0];
|
||||
@@ -71,4 +73,18 @@ 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);
|
||||
|
||||
console.log('RTA profile regression tests passed');
|
||||
|
||||
Reference in New Issue
Block a user