import { synthesizeMicrophoneSignals } from "/packages/acoustics-core/propagation.js"; import { computeDasWithBackend } from "/packages/webgpu-kernels/compute.js"; function post(type, jobId, payload = {}, transfer = []) { self.postMessage({ type, jobId, ...payload }, transfer); } function serializeError(error) { return { name: error?.name ?? "Error", code: error?.code ?? "", message: error instanceof Error ? error.message : String(error), stack: error?.stack ?? "", causes: error instanceof AggregateError ? error.errors.map((cause) => ({ name: cause?.name, code: cause?.code, message: cause?.message })) : [], }; } self.addEventListener("message", async (event) => { if (event.data?.type !== "run") return; const { jobId, scene, arrayDefinition, experiment, assetBuffers } = event.data; const totalStartedAt = performance.now(); try { post("progress", jobId, { stage: "signal", message: "192채널 자유음장 신호를 합성하고 있습니다…" }); const signalStartedAt = performance.now(); const synthesis = synthesizeMicrophoneSignals({ scene, arrayDefinition, assetBuffers, minimumDistance: experiment.beamforming.minimumDistance, }); const signalGeneration = performance.now() - signalStartedAt; post("progress", jobId, { stage: "signal-complete", message: `마이크 신호 합성 완료 · ${signalGeneration.toFixed(0)} ms`, }); const beamformingStartedAt = performance.now(); const das = await computeDasWithBackend({ channels: synthesis.channels, sampleRate: synthesis.sampleRate, arrayDefinition, scene, experiment, onFallback: ({ error }) => post("fallback", jobId, { code: error.code, message: error.message, }), onProgress: (progress) => post("progress", jobId, { stage: progress.stage, progress }), }); const beamforming = performance.now() - beamformingStartedAt; const transfer = []; for (const band of das.bands) { transfer.push(band.rawMap.buffer, band.displayMap.buffer); } post( "result", jobId, { run: { ...das, signalStats: { preNormalizationPeak: synthesis.preNormalizationPeak, appliedScale: synthesis.appliedScale, clippedSampleCount: synthesis.clippedSampleCount, peak: synthesis.peak, }, timingMs: { total: performance.now() - totalStartedAt, signalGeneration, beamforming, }, }, }, transfer, ); } catch (error) { post("error", jobId, { error: serializeError(error) }); } });