137 lines
9.9 KiB
HTML
137 lines
9.9 KiB
HTML
<!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>
|