perf: stream propagation working sets
This commit is contained in:
@@ -8,6 +8,10 @@ import {
|
||||
describeFrequencyAliasing,
|
||||
observeFrequencyBand,
|
||||
} from "/packages/acoustics-core/sampling.js";
|
||||
import {
|
||||
DEFAULT_MAXIMUM_SYNTHESIS_BUFFER_BYTES,
|
||||
estimateSynthesisWorkingSet,
|
||||
} from "/packages/acoustics-core/propagation.js";
|
||||
|
||||
async function loadJson(path) {
|
||||
const response = await fetch(path);
|
||||
@@ -481,6 +485,85 @@ test("analytic tone-only Scene은 존재하지 않는 delay FFT 메모리로 거
|
||||
);
|
||||
});
|
||||
|
||||
test("Experiment preflight는 runtime과 같은 source-streaming shoebox delay working set을 쓴다", async () => {
|
||||
const [arrayDefinition, scene, experiment] = await Promise.all([
|
||||
loadJson("/assets/array-geometries/rectangular-16x12.array.json"),
|
||||
loadJson("/assets/sample-scenes/single-tone.scene.json"),
|
||||
loadJson("/assets/sample-scenes/single-tone.experiment.json"),
|
||||
]);
|
||||
arrayDefinition.microphones = arrayDefinition.microphones.slice(0, 16);
|
||||
scene.sampleRate = 192_000;
|
||||
scene.duration = 4_000_000 / scene.sampleRate;
|
||||
scene.sources = [{
|
||||
...structuredClone(scene.sources[0]),
|
||||
id: "long-sampled-source",
|
||||
name: "Long sampled source",
|
||||
position: [0, 0, 1],
|
||||
startTime: 0,
|
||||
duration: scene.duration,
|
||||
signal: { type: "noise", color: "white", seedOffset: 1 },
|
||||
}];
|
||||
scene.ambient = [];
|
||||
scene.acoustics = {
|
||||
model: "shoebox",
|
||||
room: { min: [-10, -10, -10], max: [10, 10, 10] },
|
||||
reflections: { order: 0, wallGainDb: -12, scattering: 0 },
|
||||
diffuseReverb: {
|
||||
enabled: true,
|
||||
rt60Seconds: 4,
|
||||
gainDb: -18,
|
||||
tapCount: 1,
|
||||
},
|
||||
occluders: [],
|
||||
};
|
||||
experiment.beamforming.minimumDistance = 0.01;
|
||||
|
||||
const workingSet = estimateSynthesisWorkingSet({
|
||||
scene,
|
||||
arrayDefinition,
|
||||
minimumDistance: experiment.beamforming.minimumDistance,
|
||||
});
|
||||
assertEqual(workingSet.sampleCount, 4_000_000, "fixture sample count");
|
||||
assertEqual(
|
||||
workingSet.maximumTransient.fftSize,
|
||||
8_388_608,
|
||||
"diffuse delay crosses the FFT power-of-two boundary",
|
||||
);
|
||||
assert(
|
||||
workingSet.estimatedBufferBytes > DEFAULT_MAXIMUM_SYNTHESIS_BUFFER_BYTES,
|
||||
"shared runtime estimate exceeds 512 MiB",
|
||||
);
|
||||
const issues = await validateExperiment(experiment, {
|
||||
arrayDefinition,
|
||||
scene,
|
||||
});
|
||||
assert(
|
||||
issues.some(({ message }) =>
|
||||
message.includes("source-streaming") && message.includes("512 MiB")),
|
||||
`validator must reject the same shared estimate: ${JSON.stringify(issues)}`,
|
||||
);
|
||||
|
||||
scene.sources[0].signal = { type: "tone", frequency: 1_000, phaseDeg: 0 };
|
||||
const toneWorkingSet = estimateSynthesisWorkingSet({
|
||||
scene,
|
||||
arrayDefinition,
|
||||
minimumDistance: experiment.beamforming.minimumDistance,
|
||||
});
|
||||
assertEqual(
|
||||
toneWorkingSet.estimatedBufferBytes,
|
||||
toneWorkingSet.channelBytes,
|
||||
"analytic tone has no sampled FFT transient",
|
||||
);
|
||||
const toneIssues = await validateExperiment(experiment, {
|
||||
arrayDefinition,
|
||||
scene,
|
||||
});
|
||||
assert(
|
||||
!toneIssues.some(({ message }) => message.includes("512 MiB")),
|
||||
"validator does not charge analytic tone for a nonexistent delay FFT",
|
||||
);
|
||||
});
|
||||
|
||||
test("NaN 좌표를 거부한다", async () => {
|
||||
const arrayDefinition = {
|
||||
schemaVersion: "1.0.0", kind: "micarrsim.array", id: "nan-test", name: "NaN test", units: "m",
|
||||
|
||||
Reference in New Issue
Block a user