# micarrsim 실행 계획 ## 1. 목표와 성공 기준 이 프로젝트는 정방형 평면에 배치할 192개 MEMS 마이크의 배열을 비교하기 위한 재현 가능한 시뮬레이터를 만든다. 첫 버전은 자유음장(free field), 점 음원, 구면파 전파를 가정하며 다음 흐름을 끝까지 수행해야 한다. 1. 기계음 데이터와 ambient audio를 조합해 장면 및 ground truth를 생성한다. 2. 배열 JSON과 장면 정보를 사용해 각 마이크에 도달하는 신호를 합성한다. 3. WGSL로 conventional delay-and-sum(DAS/DAC) 빔포밍을 수행한다. 4. 주파수 구간별 acoustic image를 ground truth 위에 표시하고 정량 평가한다. 5. 배열, 거리, 음원, 주파수, grid 해상도를 바꾼 실험을 저장하고 비교한다. 최소 성공 기준은 192채널, 50×50 scan grid, 단일 및 복수 음원에서 결과를 대화형으로 만들고, CPU 기준 구현과 GPU 결과의 수치 오차가 합의된 허용 범위 안에 있으며, 동일 seed와 설정으로 실험을 재현할 수 있는 것이다. ## 2. 기술 접근 결정 TypeScript 기반의 브라우저 앱 2개와 WebGPU/WGSL을 권장한다. 브라우저는 배열·장면 편집, 오디오 미리 듣기, 이미지 overlay에 적합하고 WebGPU는 192 × scan point × frequency bin 형태의 병렬 연산에 잘 맞는다. WGSL 커널을 독립 패키지로 두면 이후 GLSL 또는 네이티브 GPU 구현으로 옮길 때 데이터 배치와 수식을 재사용하기 쉽다. 데이터셋 전체를 브라우저에 적재하지 않는다. 사용자가 로컬 파일을 선택해 장면을 만들고, 결과를 manifest와 오디오 파일로 내보내는 방식을 우선 구현한다. 대규모 batch 전처리가 필요해질 때만 동일 스키마를 쓰는 별도 CLI를 추가한다. 이 방식은 초기 복잡도를 줄이면서 확장 경로를 남긴다. 두 앱의 책임은 다음과 같이 분리한다. - `dataset-builder`: 음원 배치, gain/시간 구간/반복 설정, ambient mix, 이미지상의 위치 지정, seed 고정, 합성 오디오와 ground truth manifest 내보내기 - `acoustic-camera`: manifest와 배열 JSON 읽기, 마이크 신호 전파 합성, steering vector 생성, DAS 실행, overlay·수치 평가·실험 결과 내보내기 - `acoustics-core`: 두 앱이 공유하는 좌표계, 단위, 구면 감쇠·지연, STFT, 정답 rasterization, 지표 및 CPU reference - `webgpu-kernels`: steering/DAS 커널, buffer layout, 장치 한도 검사와 benchmark ## 3. 데이터 계약 JSON Schema를 먼저 고정하고 모든 길이는 m, 시간은 s, 주파수는 Hz, 좌표는 우수 좌표계로 명시한다. - `array.schema.json`: schema version, 배열 폭·높이, 192개 마이크의 id와 `[x,y,z]`, 선택적 감도·채널 보정값 - `scene.schema.json`: 배경 이미지 크기와 실제 평면 변환, 음원별 위치·오디오 참조·시작/종료· gain, ambient 참조, sample rate, seed - `experiment.schema.json`: 배열/장면 참조, AC-음원 거리, 음속, frequency band 목록과 색, STFT window/hop, scan bounds와 해상도, 알고리즘 및 normalization - `result.schema.json`: 실행 환경, timing, acoustic map, peak, 평가 지표, 입력 hash 오디오 파일은 manifest 옆의 상대 경로로 참조한다. 브라우저 내 객체 URL은 저장 형식에 포함하지 않는다. 스키마에는 버전을 두고 향후 잔향 모델과 마이크 지향성을 선택 필드로 추가한다. ## 4. 음향 및 연산 모델 첫 모델에서 음원 `s`와 마이크 `m` 사이 거리 `r`에 대해 지연은 `r/c`, 진폭은 기준 거리와 최소 거리 clamp를 둔 `1/r`로 계산한다. 분수 sample 지연은 주파수 영역의 phase shift로 처리한다. 복수 음원과 ambient를 선형 합산하되 clipping 전 peak와 최종 normalization을 기록한다. DAS는 STFT 후 각 scan point와 마이크 사이 거리로 steering phase를 만들고, 선택된 주파수 bin의 정렬 합 power를 계산한다. 여러 주파수 구간은 각각 독립 map과 색을 갖는다. CPU reference를 먼저 작성한 뒤 같은 buffer layout으로 WGSL 결과를 대조한다. DAMAS, CLEAN-SC는 인터페이스만 마련하고 초기 완료 범위에서는 제외한다. 연산량의 주항은 대략 `O(P × M × F)`다. `M=192`, `P=50²=2,500`일 때 주파수 bin 하나당 약 48만 개의 복소 steering 누산이 필요하다. 100×100은 50×50보다 4배, 200×200은 16배이므로 장치별 실제 GPU timing을 UI에 표시하고 목표 frame budget에 맞춰 해상도를 제한한다. 정확한 성능과 메모리는 대표 GPU에서 benchmark하여 기록하며 이론치만으로 약속하지 않는다. ## 5. UI 계획 `acoustic-camera`는 폭 600px 이상인 좌측 scene canvas에 기기 이미지, ground-truth hint, 주파수별 acoustic overlay를 표시한다. 우측에는 배열 geometry를 확대·회전 가능한 평면도로 표시하고 그 아래에 제어 패널을 둔다. 작은 화면에서는 두 열을 세로로 쌓는다. 필수 입력은 음원 수와 위치, AC 거리, 다중 주파수 구간과 색, ambient 파일, scan grid 크기, 후처리 선택이다. 여기에 sample rate, 음속/온도, STFT window·hop, scan 영역, dynamic range, colormap/opacity, 음원별 gain·시작 시간, random seed, 정규화 방법을 추가한다. 잘못된 단위, Nyquist 초과 대역, WebGPU buffer 한도는 실행 전에 검증한다. ## 6. 평가 방법 점 음원 위치를 image plane으로 투영해 ground-truth heatmap과 위치 목록을 함께 저장한다. 최소 지표는 다음과 같다. - peak localization error(m 및 pixel) - 정답 반경 안 에너지 / 전체 에너지 - main-lobe width와 peak-to-sidelobe ratio - 복수 음원 검출 precision/recall(거리 tolerance 명시) - 실행 시간, GPU 메모리 추정량, grid 해상도별 scaling 합성 신호의 해석 가능한 단일 tone/단일 음원 case를 golden test로 두고, broadband·복수 음원· ambient 순으로 난도를 높인다. 배열 비교에는 같은 scene, seed, STFT, scan grid를 사용한다. ## 7. 데이터셋 조사 및 라이선스 관문 DCASE Task 2와 MIMII의 샘플 구조, 녹음 조건, channel 구성, 라이선스와 재배포 조건을 확인한 뒤 채택한다. 초기에는 저장소에 포함할 수 있는 synthetic tone/noise로 전체 pipeline을 검증한다. 실제 데이터는 사용자가 별도로 받아 연결하며 원본이나 파생 대용량 오디오는 Git에서 제외한다. DCASE/MIMII가 위치별 분리 음원으로 쓰기 어려우면 기계 종류별 clip 추출·정규화 규칙을 문서화하고, flattening이 모델 타당성을 훼손하는지 청취 및 spectrum 통계로 평가한다. ## 8. 단계별 구현 ### 단계 0 — 기반과 계약 - workspace, formatter, linter, unit test, WebGPU feature detection 구성 - 네 가지 JSON Schema와 최소 예제 작성 - 좌표계·단위·오디오 normalization 결정 기록 - synthetic single-tone scene과 192채널 기준 배열 작성 완료 조건: 예제 JSON이 schema validation을 통과하고 두 앱이 동일 manifest를 읽는다. ### 단계 1 — CPU 기준 모델 - 자유음장 구면 전파, 분수 지연, STFT, steering, DAS의 CPU reference 구현 - 단일 음원의 지연·감쇠·peak 위치를 analytic result와 비교 - 50×50 기준 정확도와 실행 시간 측정 완료 조건: 자동화된 golden test가 통과하고 sign/좌표 convention이 문서화된다. ### 단계 2 — Dataset Builder - 이미지와 음원 파일 불러오기, 위치·시간·gain 편집, ambient mix와 미리 듣기 - deterministic seed, clipping 경고, manifest/audio 내보내기 - 데이터셋 adapter 인터페이스와 synthetic adapter 구현 완료 조건: 만든 scene을 다시 열었을 때 음원, 위치, 파형, 정답이 동일하다. ### 단계 3 — WebGPU DAS - CPU와 동일한 buffer layout 및 WGSL kernel 구현 - frequency band별 map 생성, device limit 대응, CPU fallback - 50²/100²/200² 및 band/bin 수에 따른 benchmark 완료 조건: CPU/GPU map 오차 기준을 통과하고 192채널 50×50 실행 timing이 기록된다. ### 단계 4 — Acoustic Camera UI와 평가 - scene/ground truth/acoustic overlay, 배열 geometry, parameter panel 구현 - 결과 metric, 실행 환경, 입력 hash와 map 내보내기 - 복수 음원·다중 대역 표시와 실험 preset 비교 완료 조건: 사용자가 코드 수정 없이 배열 JSON 두 개를 같은 장면에서 비교할 수 있다. ### 단계 5 — 실제 데이터와 고도화 - 라이선스 검토를 통과한 DCASE/MIMII adapter와 batch workflow 추가 - microphone calibration·noise 모델 검토 - 필요 시 DAMAS/CLEAN-SC를 플러그인형 후처리로 추가 - image-source method 또는 room impulse response 기반 잔향 모듈 추가 완료 조건: 자유음장 결과를 훼손하지 않고 propagation model을 선택해 재실행할 수 있다. ## 9. 주요 위험과 대응 - WebGPU 미지원/장치 한도: 시작 시 capability를 표시하고 CPU fallback 및 grid 상한을 둔다. - 좌표·phase 부호 오류: analytic tone test와 배열 대칭성 test를 먼저 만든다. - 브라우저 메모리: 전체 시간×192 신호를 항상 보관하지 않고 chunk/STFT frame 단위로 처리한다. - 데이터셋 부적합/라이선스: adapter 경계를 유지하고 synthetic fixture를 기본 CI 입력으로 쓴다. - 실제 AC와 simulation gap: 감도, 위상, 위치 오차를 이후 calibration/noise model로 주입 가능하게 한다. - post-processing이 기본 결과를 가림: raw DAS map과 후처리 map을 항상 별도로 보존한다. ## 10. 첫 구현 백로그 1. TypeScript workspace와 두 앱 shell을 생성한다. 2. array/scene/experiment/result schema와 fixture를 만든다. 3. 좌표 변환, 거리, 구면 감쇠, 주파수 phase delay 단위 테스트를 작성한다. 4. CPU DAS golden implementation과 synthetic scene을 만든다. 5. WGSL kernel 및 CPU/GPU 비교 harness를 만든다. 6. scene canvas, array view, parameter controls를 연결한다. 7. benchmark와 평가 지표를 결과 manifest에 기록한다. 각 단계는 정확성 test를 먼저 통과시킨 뒤 UI 또는 최적화를 진행한다. 초기 milestone에서는 잔향, DAMAS/CLEAN-SC, 대규모 dataset batch 변환을 완료 조건으로 삼지 않는다.