feat: add built-in array comparison

This commit is contained in:
Codex
2026-08-28 12:19:42 +09:00
parent d04a4d9f65
commit 2ce96064cf
7 changed files with 1670 additions and 1 deletions
+37
View File
@@ -23,6 +23,10 @@ const DEFAULT_DOCUMENT_URLS = {
scene: "/assets/sample-scenes/single-tone.scene.json",
experiment: "/assets/sample-scenes/single-tone.experiment.json",
};
const ARRAY_PRESET_URLS = new Map([
["rectangular-16x12", "/assets/array-geometries/rectangular-16x12.array.json"],
["fermat-spiral-192", "/assets/array-geometries/fermat-spiral-192.array.json"],
]);
const BAND_COLORS = ["#65f2bf", "#58c7ff", "#ff7f8f", "#ffc56e", "#b294ff", "#8fe388", "#ff9ee5", "#83a8ff"];
const MAX_HISTORY_ITEMS = 24;
@@ -51,6 +55,7 @@ const elements = {
historyList: byId("history-list"),
arrayTitle: byId("array-title"),
microphoneCount: byId("microphone-count"),
arrayPreset: byId("array-preset"),
arrayCanvas: byId("array-canvas"),
arrayMeta: byId("array-meta"),
sourceSummary: byId("source-summary"),
@@ -223,6 +228,9 @@ function syncControls() {
elements.hopSize.value = experiment.stft.hopSize;
elements.normalization.value = experiment.beamforming.normalization;
elements.dynamicRange.value = experiment.beamforming.dynamicRangeDb;
elements.arrayPreset.value = ARRAY_PRESET_URLS.has(state.arrayDefinition.id)
? state.arrayDefinition.id
: "custom";
elements.gridPreset.value =
experiment.scan.columns === experiment.scan.rows && [50, 100, 200].includes(experiment.scan.rows)
? String(experiment.scan.rows)
@@ -855,6 +863,34 @@ async function loadJson(url) {
return response.json();
}
async function loadArrayPreset(presetId) {
const url = ARRAY_PRESET_URLS.get(presetId);
if (!url) {
elements.arrayInput.click();
syncControls();
return;
}
const generation = ++state.importGenerations.array;
beginInputOperation();
try {
setRunStatus(`${presetId} 비교 배열을 불러오고 있습니다…`);
const value = await loadJson(url);
if (generation !== state.importGenerations.array) return;
const issues = await validateArrayDefinition(value);
if (generation !== state.importGenerations.array) return;
if (issues.length > 0) throw new Error(issues.slice(0, 4).map(formatIssue).join(" · "));
state.arrayDefinition = value;
state.experiment.arrayId = value.id;
markChanged({ syncControls: true });
setRunStatus(`${value.name} 배열을 선택했습니다. 실행하면 같은 설정 기록에 추가됩니다.`);
} catch (error) {
syncControls();
setTransientError(error, "비교 배열 불러오기 실패");
} finally {
endInputOperation();
}
}
async function importDocument(kind, input) {
const file = input.files?.[0];
input.value = "";
@@ -1039,6 +1075,7 @@ function installActionListeners() {
"change",
() => importDocument("experiment", elements.experimentInput),
);
elements.arrayPreset.addEventListener("change", () => loadArrayPreset(elements.arrayPreset.value));
elements.assetInput.addEventListener("change", async () => {
const files = [...(elements.assetInput.files ?? [])];
elements.assetInput.value = "";