commit bfc37e76c73c0802bb1de229673eef2673161b35 Author: Codex Date: Fri Aug 28 08:43:30 2026 +0900 docs: define simulator execution plan diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a2b797 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Dependencies and build output +node_modules/ +dist/ +build/ +coverage/ +.cache/ + +# Local configuration +.env +.env.* +!.env.example + +# Editors and operating systems +.idea/ +.vscode/ +.DS_Store +Thumbs.db + +# Large/local acoustic data and generated results +data/ +datasets/ +results/ +artifacts/ +*.wav +*.flac +*.mp3 + +# Keep explicitly curated fixtures if they are added later +!assets/sample-scenes/**/*.wav +!assets/sample-scenes/**/*.flac diff --git a/README.md b/README.md new file mode 100644 index 0000000..649972f --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# micarrsim + +192채널 MEMS 마이크 배열의 배치와 음향 영상 성능을 평가하기 위한 WebGPU 기반 시뮬레이터입니다. + +현재는 설계 단계입니다. 프로젝트 목표는 [`goal.md`](goal.md), 구현 로드맵과 기술 결정은 +[`docs/execution-plan.md`](docs/execution-plan.md)를 참고하세요. + +## 디렉터리 + +```text +apps/ + dataset-builder/ 음원 합성 및 ground truth 생성 UI + acoustic-camera/ 전파, DAC 빔포밍, 평가 및 시각화 UI +packages/ + acoustics-core/ 공통 좌표계, 음향 모델, 평가 로직 + webgpu-kernels/ WGSL 기반 steering/DAC 연산 +schemas/ 배열·장면·실험 JSON Schema +assets/ + array-geometries/ 마이크 배열 예제 + sample-scenes/ 재배포 가능한 소규모 예제 장면 +tests/ + unit/ 수치 모델 단위 테스트 + integration/ 앱 간 데이터 계약과 기준 시나리오 테스트 +docs/ 설계 및 실행 계획 +``` + +원본 DCASE/MIMII 데이터와 생성된 대용량 결과는 저장소에 커밋하지 않습니다. diff --git a/apps/acoustic-camera/README.md b/apps/acoustic-camera/README.md new file mode 100644 index 0000000..2be0f5f --- /dev/null +++ b/apps/acoustic-camera/README.md @@ -0,0 +1,3 @@ +# Acoustic Camera + +scene과 마이크 배열을 불러와 자유음장 전파, WGSL DAS 빔포밍, overlay 및 평가를 수행하는 앱입니다. diff --git a/apps/dataset-builder/README.md b/apps/dataset-builder/README.md new file mode 100644 index 0000000..31db6fb --- /dev/null +++ b/apps/dataset-builder/README.md @@ -0,0 +1,3 @@ +# Dataset Builder + +음원, ambient audio, 이미지상의 위치를 조합해 scene audio와 ground truth manifest를 만드는 앱입니다. diff --git a/assets/array-geometries/README.md b/assets/array-geometries/README.md new file mode 100644 index 0000000..05fb812 --- /dev/null +++ b/assets/array-geometries/README.md @@ -0,0 +1,3 @@ +# Array Geometries + +재현 가능한 마이크 배열 JSON 예제를 둡니다. diff --git a/assets/sample-scenes/README.md b/assets/sample-scenes/README.md new file mode 100644 index 0000000..06ebcbb --- /dev/null +++ b/assets/sample-scenes/README.md @@ -0,0 +1,3 @@ +# Sample Scenes + +재배포 가능한 최소 synthetic scene과 fixture를 둡니다. diff --git a/docs/execution-plan.md b/docs/execution-plan.md new file mode 100644 index 0000000..5f05f12 --- /dev/null +++ b/docs/execution-plan.md @@ -0,0 +1,178 @@ +# 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 변환을 완료 조건으로 삼지 않는다. diff --git a/goal.md b/goal.md new file mode 100644 index 0000000..9baa000 --- /dev/null +++ b/goal.md @@ -0,0 +1,33 @@ +정방형 평면에 192개의 MEMS마이크를 배치한 acoustic camera(이하 AC)를 만들계획이다. +192개나 되는 마이크의 배열을 어찌해야할지 정해야하기 때문에, 아래의 시뮬레이션을 만들어야 한다. +1. 음원을 주워다가 발음시키고, +2. 그 발음된 소리를 AC에 도달시키고 +3. AC는 DAC를 수행(DAMAS나 clean-sc같은거는 후처리니까 나중에 할 것)해서 acoustic image를 얻는다. +4. 음원을 우리가 합성해서 재생했으니까, 그 ground truth를 바탕으로 평가까지 해야하고, +5. 배치는 물론 이런저런 파라메터를 바꾸면서 테스트해볼 수 있는 시뮬레이션 + +시뮬레이션 작성은 브라우저+GPU가 빠를것으로 생각되나, 더 나은 접근이 있다면 그것을 제시해라 +다만 WGSL로 작업하면 나중에 행렬연산은 glsl로 포팅하기 쉬울 것이므로 약간의 가중치가 있다. + +화면에는 오른편에 마이크배열의 geometry, (마이크 배열은 json으로 그 크기와 각 마이크의 좌표를 받아올 수 있도록) +왼편에는 기기의 이미지 grid랑 정답의 정보/힌트, 그리고 우리가 빔포밍을 수행한 결과의 overlay가 있어야 한다. +이미지 크기는 폭을 최소, 대략 600px정도 잡으면 되겠고, 빔포밍은 50x50정도가 하한이다. (더 정밀하게 하려면 컴퓨팅 파워가 얼마나 더 필요하게 될지 추산도 필요하다) +하단에는 오른편 마이크배열 그림 아래에는 각종 파라메터 입력이 있어야 한다. + +파라메터의 종류는 음원의 갯수, 음원으로부터의 거리(조절가능), 보고싶은 주파수대역(멀티구간으로, 다른색), +추가하고싶은 ambient sound파일, 빔포밍포인트수, 후처리알고리즘 선택, 등이 되겠다. 더 필요해보이는게 있다면 역시 제시해라. + + +음원을 만들려면 ambient 도 있어야하고, 특정 부분에서 나는 소리도 있어야 할것으로 예상되는데, +그걸 합성할 데이터셋은 DCASE 의 task 2를 쓰거나 - (요소로 쓰기좋게 flatten 하기엔 안좋을 수도 있으니 별도의 평가가 필요하다) +MIMII dataset 같은거를 쓰면 아마 바라보는 장면의 특정 부위에서 기기의 소리가 나도록 데이터셋을 구성할 수 있을 것이다. +거기에 AC는 음원에서 수 m 떨어져있을테니까 거리도 조절 할 수 있도록 해야한다. +일단은 잔향은 배제하고 구형으로 전파되는 상황을 가정해서 시뮬레이션 해라. 다만 추후 잔향 시뮬레이션이 필요할수 있으므로 확장 가능성을 염두에 둬라. + +데이터셋/정답을 만드는 프로그램과 그걸 playback 해서 DAC를 수행하는 프로그램을 분리해서 만들어라. +html 페이지 둘로 만드는게 나을 수도 있는데, ground truth 만들기가 쉽고 빠르다면 그냥 만들어도 무방하다. 이에 대한건 스스로 한번 평가해라. + +정리하자면 이 프로젝트의 골은 +1. 데이터 셋으로부터, 실제 환경에서 나는 것 같은 음원을 만들고, +2. 마이크 정보를 가지고 steering vector를 만들어서, 그 소리를 듣는 것을 시뮬레이션 하고, +3. 그것으로 acoustic image를 만드는 또 다른 시뮬레이션을 WGSL 사용하여 만든다. \ No newline at end of file diff --git a/packages/acoustics-core/README.md b/packages/acoustics-core/README.md new file mode 100644 index 0000000..afee959 --- /dev/null +++ b/packages/acoustics-core/README.md @@ -0,0 +1,3 @@ +# Acoustics Core + +두 앱이 공유하는 좌표계, 자유음장 전파, STFT, CPU 기준 DAS 및 평가 로직을 둡니다. diff --git a/packages/webgpu-kernels/README.md b/packages/webgpu-kernels/README.md new file mode 100644 index 0000000..8b70d10 --- /dev/null +++ b/packages/webgpu-kernels/README.md @@ -0,0 +1,3 @@ +# WebGPU Kernels + +WGSL steering vector 및 DAS 연산과 GPU buffer layout, benchmark 코드를 둡니다. diff --git a/schemas/README.md b/schemas/README.md new file mode 100644 index 0000000..ef5f5c7 --- /dev/null +++ b/schemas/README.md @@ -0,0 +1,3 @@ +# Schemas + +마이크 배열, scene, experiment, result의 versioned JSON Schema를 둡니다. diff --git a/tests/integration/README.md b/tests/integration/README.md new file mode 100644 index 0000000..61b300e --- /dev/null +++ b/tests/integration/README.md @@ -0,0 +1,3 @@ +# Integration Tests + +두 앱 사이 manifest 계약과 end-to-end golden scenario를 검증합니다. diff --git a/tests/unit/README.md b/tests/unit/README.md new file mode 100644 index 0000000..cbd1df0 --- /dev/null +++ b/tests/unit/README.md @@ -0,0 +1,3 @@ +# Unit Tests + +음향 수식, 좌표 변환, CPU/GPU 수치 일치 테스트를 둡니다.