Files
micarrsim/apps/acoustic-camera/index.html
T
2026-08-28 12:19:42 +09:00

137 lines
9.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="192채널 WebGPU acoustic camera simulator" />
<title>Acoustic Camera · micarrsim</title>
<link rel="stylesheet" href="/packages/ui/app-shell.css" />
<link rel="stylesheet" href="/apps/acoustic-camera/styles.css" />
</head>
<body>
<div class="app-shell camera-shell">
<header class="app-header camera-header">
<a class="app-brand" href="/"><strong>micarrsim</strong><span>Acoustic Camera</span></a>
<div class="header-status">
<span class="status-chip status-chip--neutral" data-runtime-status>런타임 확인 중…</span>
<span class="run-status" id="run-status">기본 fixture 준비 중…</span>
</div>
<div class="header-actions">
<button class="button button--ghost is-hidden" id="cancel-button" type="button">계산 취소</button>
<button class="button button--ghost" id="export-result-button" type="button" disabled>Result JSON</button>
<button class="button button--primary" id="run-button" type="button" disabled>▶ 기본 예제 실행</button>
</div>
</header>
<main class="camera-layout">
<section class="scene-workspace" aria-label="Acoustic image workspace">
<div class="workspace-heading">
<div>
<p class="eyebrow">Ground truth + acoustic overlay</p>
<h1 id="workspace-title">음향 장면</h1>
<p class="workspace-meta" id="scene-meta">장면을 불러오고 있습니다.</p>
</div>
<div class="workspace-tools" aria-label="입력 파일">
<label class="button button--ghost file-button">Scene<input id="scene-input" type="file" accept="application/json,.json" /></label>
<label class="button button--ghost file-button">Array<input id="array-input" type="file" accept="application/json,.json" /></label>
<label class="button button--ghost file-button">Experiment<input id="experiment-input" type="file" accept="application/json,.json" /></label>
<label class="button button--ghost file-button">Assets<input id="asset-input" type="file" accept="audio/*,image/*,.wav,.flac,.mp3,.ogg,.m4a,.png,.jpg,.jpeg,.webp,.svg" multiple /></label>
</div>
</div>
<div class="scene-canvas-card">
<canvas id="scene-canvas" aria-label="Ground truth와 주파수별 acoustic image"></canvas>
<div class="canvas-message" id="canvas-message"><strong>기본 synthetic scene이 준비됩니다.</strong><span>실행하면 주파수별 acoustic image가 이 평면에 겹쳐집니다.</span></div>
<div class="canvas-badge" id="canvas-badge">결과 없음</div>
</div>
<div class="overlay-toolbar">
<div class="band-legend" id="band-legend" aria-label="표시 주파수 대역"></div>
<label class="range-field"><span>Overlay</span><input id="overlay-opacity" type="range" min="0" max="1" step="0.05" value="0.72" /></label>
<label class="check-field"><input id="show-truth" type="checkbox" checked /><span>Ground truth</span></label>
</div>
<section class="result-section" aria-live="polite">
<div class="section-heading"><div><p class="eyebrow">Evaluation</p><h2>실행 결과</h2></div><span class="result-chip" id="result-badge">아직 실행하지 않음</span></div>
<div class="empty-result" id="empty-result">시뮬레이션을 실행하면 위치 오차, energy concentration, sidelobe와 timing을 표시합니다.</div>
<div class="metric-grid is-hidden" id="metric-grid"></div>
</section>
<section class="history-section">
<div class="section-heading"><div><p class="eyebrow">Same-scene comparison</p><h2>배열 비교 기록</h2></div><button class="text-button" id="clear-history-button" type="button">기록 비우기</button></div>
<p class="section-copy">비교 배열 또는 Array JSON을 바꿔 다시 실행하면 같은 scene·scan·STFT 결과를 이 세션에서 나란히 비교합니다.</p>
<div class="history-list" id="history-list"></div>
</section>
</section>
<aside class="control-panel" aria-label="Simulation parameters">
<section class="array-card">
<div class="array-heading"><div><p class="eyebrow">Microphone geometry</p><h2 id="array-title">배열</h2></div><strong id="microphone-count">— ch</strong></div>
<label class="array-preset-field"><span>비교 배열</span><select id="array-preset"><option value="rectangular-16x12">16×12 rectangular · 기준</option><option value="fermat-spiral-192">Fermat spiral · 비교</option><option value="custom">불러온 Array JSON</option></select></label>
<canvas id="array-canvas" aria-label="마이크 배열 평면도"></canvas>
<p id="array-meta">배열을 불러오고 있습니다.</p>
</section>
<section class="asset-card">
<div class="section-title"><span>INPUT</span><h2>장면과 assets</h2></div>
<div class="source-summary" id="source-summary"></div>
<div class="asset-list" id="asset-list"></div>
<a class="builder-link" href="/apps/dataset-builder/">음원 위치·ambient 편집은 Dataset Builder에서 →</a>
</section>
<section class="control-section">
<div class="section-title"><span>01</span><h2>실험</h2></div>
<label class="field field--wide"><span>이름</span><input id="experiment-name" type="text" maxlength="120" /></label>
<label class="field field--wide"><span>Experiment ID</span><input id="experiment-id" type="text" maxlength="120" /></label>
<div class="field-grid">
<label class="field"><span>Scene 거리 z (m)</span><input id="scene-distance" type="number" min="0.01" step="0.1" /></label>
<label class="field"><span>음속 (m/s)</span><input id="speed-of-sound" type="number" min="250" max="400" step="0.1" /></label>
<label class="field"><span>Seed</span><input id="scene-seed" type="number" min="0" max="4294967295" step="1" /></label>
<label class="field"><span>Backend</span><select id="backend"><option value="auto">Auto (GPU→CPU)</option><option value="webgpu">WebGPU 강제</option><option value="cpu">CPU 강제</option></select></label>
</div>
</section>
<section class="control-section">
<div class="section-title"><span>02</span><h2>Scan grid</h2></div>
<label class="field field--wide"><span>Preset</span><select id="grid-preset"><option value="50">50×50 · 기준</option><option value="100">100×100 · 4× points</option><option value="200">200×200 · 16× points</option><option value="custom">직접 입력</option></select></label>
<div class="field-grid">
<label class="field"><span>Columns</span><input id="scan-columns" type="number" min="8" max="512" step="1" /></label>
<label class="field"><span>Rows</span><input id="scan-rows" type="number" min="8" max="512" step="1" /></label>
<label class="field"><span>x min (m)</span><input id="scan-x-min" type="number" step="0.05" /></label>
<label class="field"><span>x max (m)</span><input id="scan-x-max" type="number" step="0.05" /></label>
<label class="field"><span>y min (m)</span><input id="scan-y-min" type="number" step="0.05" /></label>
<label class="field"><span>y max (m)</span><input id="scan-y-max" type="number" step="0.05" /></label>
</div>
<p class="workload-summary" id="workload-summary">연산량 계산 중…</p>
</section>
<section class="control-section">
<div class="section-title"><span>03</span><h2>STFT와 표시</h2></div>
<div class="field-grid">
<label class="field"><span>FFT size</span><select id="fft-size"><option>128</option><option>256</option><option selected>512</option><option>1024</option><option>2048</option><option>4096</option></select></label>
<label class="field"><span>Hop size</span><input id="hop-size" type="number" min="1" max="4096" step="1" /></label>
<label class="field"><span>Map 정규화</span><select id="normalization"><option value="peak">Peak</option><option value="none">없음</option></select></label>
<label class="field"><span>Dynamic range (dB)</span><input id="dynamic-range" type="number" min="6" max="120" step="1" /></label>
<label class="field field--wide"><span>후처리</span><select id="postprocess"><option value="none">없음 · raw DAS</option><option disabled>DAMAS · 후속 milestone</option><option disabled>CLEAN-SC · 후속 milestone</option></select></label>
</div>
</section>
<section class="control-section">
<div class="section-title section-title--spread"><div><span>04</span><h2>주파수 대역</h2></div><button class="mini-button" id="add-band-button" type="button">+ 대역</button></div>
<div class="band-editor-list" id="band-list"></div>
</section>
<section class="output-card"><button class="button button--ghost button--full" id="export-experiment-button" type="button">Experiment JSON 저장</button></section>
<section class="validation-card" aria-live="polite">
<div class="validation-dot" id="validation-dot"></div>
<div><strong id="validation-title">검증 대기</strong><p id="validation-message">입력을 준비하고 있습니다.</p></div>
</section>
</aside>
</main>
</div>
<script type="module" src="/packages/ui/runtime-status.js"></script>
<script type="module" src="/apps/acoustic-camera/main.js"></script>
</body>
</html>