feat: add physically explicit narrowband MUSIC
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import { synthesizeMicrophoneSignals } from "/packages/acoustics-core/propagation.js";
|
||||
import { sampleQuasiStaticWindow } from "/packages/acoustics-core/trajectory.js";
|
||||
import { createLocalizationAnalysisPlan } from "/packages/acoustics-core/localization.js";
|
||||
import { localizationAlgorithmSupportsBackend } from "/packages/acoustics-core/localization-algorithms.js";
|
||||
import { computeLocalizationWithBackend } from "/packages/webgpu-kernels/compute.js";
|
||||
import { isMusicUnavailableError } from "/packages/acoustics-core/music.js";
|
||||
import { getCompleteFrameCount } from "/packages/acoustics-core/stft.js";
|
||||
|
||||
function post(type, jobId, payload = {}, transfer = []) {
|
||||
self.postMessage({ type, jobId, ...payload }, transfer);
|
||||
@@ -35,8 +38,47 @@ function signalStats(synthesis) {
|
||||
}
|
||||
|
||||
function collectBandTransfers(run, transfer) {
|
||||
for (const band of run.bands) {
|
||||
transfer.push(band.rawMap.buffer, band.displayMap.buffer);
|
||||
const knownBuffers = new Set(transfer);
|
||||
for (const band of run.bands ?? []) {
|
||||
for (const map of [band.rawMap, band.displayMap]) {
|
||||
const buffer = map?.buffer;
|
||||
if (buffer instanceof ArrayBuffer && !knownBuffers.has(buffer)) {
|
||||
knownBuffers.add(buffer);
|
||||
transfer.push(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function computeLocalizationOrUnavailable(options) {
|
||||
try {
|
||||
return await computeLocalizationWithBackend(options);
|
||||
} catch (error) {
|
||||
if (!isMusicUnavailableError(error)) throw error;
|
||||
return {
|
||||
algorithm: "music",
|
||||
backend: "cpu",
|
||||
status: "unavailable",
|
||||
unavailable: {
|
||||
code: error.code,
|
||||
reason: error.reason,
|
||||
message: error.message,
|
||||
details: { ...error.details },
|
||||
},
|
||||
frameCount: getCompleteFrameCount(
|
||||
options.channels[0]?.length ?? 0,
|
||||
options.experiment.stft.fftSize,
|
||||
options.experiment.stft.hopSize,
|
||||
),
|
||||
microphoneCount:
|
||||
options.arrayDefinition.microphones.length,
|
||||
pointCount:
|
||||
options.experiment.scan.rows *
|
||||
options.experiment.scan.columns,
|
||||
objectiveDirection: "minimum",
|
||||
rawScale: "noise-projection",
|
||||
bands: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +96,9 @@ async function runTimeline({ jobId, scene, arrayDefinition, experiment, assetBuf
|
||||
const localizationScene = { speedOfSound: scene.speedOfSound };
|
||||
const algorithm = experiment.beamforming.algorithm ?? "das";
|
||||
const requestedBackend = experiment.beamforming.backend ?? "auto";
|
||||
const reuseCpuPlan = algorithm === "gcc-phat" || requestedBackend === "cpu";
|
||||
const reuseCpuPlan =
|
||||
!localizationAlgorithmSupportsBackend(algorithm, "webgpu") ||
|
||||
requestedBackend === "cpu";
|
||||
let localizationExperiment = experiment;
|
||||
let analysisPlan = reuseCpuPlan
|
||||
? createLocalizationAnalysisPlan({
|
||||
@@ -105,7 +149,7 @@ async function runTimeline({ jobId, scene, arrayDefinition, experiment, assetBuf
|
||||
signalGeneration += frameSignalGeneration;
|
||||
|
||||
const localizationStartedAt = performance.now();
|
||||
const localization = await computeLocalizationWithBackend({
|
||||
const localization = await computeLocalizationOrUnavailable({
|
||||
channels: synthesis.channels,
|
||||
sampleRate: synthesis.sampleRate,
|
||||
arrayDefinition,
|
||||
@@ -234,7 +278,7 @@ self.addEventListener("message", async (event) => {
|
||||
});
|
||||
|
||||
const localizationStartedAt = performance.now();
|
||||
const localization = await computeLocalizationWithBackend({
|
||||
const localization = await computeLocalizationOrUnavailable({
|
||||
channels: synthesis.channels,
|
||||
sampleRate: synthesis.sampleRate,
|
||||
arrayDefinition,
|
||||
|
||||
Reference in New Issue
Block a user