253 lines
15 KiB
Markdown
253 lines
15 KiB
Markdown
# micarrsim
|
||
|
||
192채널 MEMS 마이크 배열의 배치와 자유음장·저비용 실내 근사에서의 DAS 음향 영상을 비교하는 로컬 브라우저
|
||
시뮬레이터입니다. Dataset Builder에서 녹음 파일·합성 신호와 이동 경로를 포함한 재현 가능한
|
||
음향 장면을 만들고 Acoustic Camera에서 CPU 또는 WebGPU로 배열 응답, acoustic map과 위치 검출
|
||
지표를 계산하거나 이동 장면을 시간축으로 재생합니다.
|
||
|
||
별도 프로그램이나 패키지를 설치하지 않습니다. 모든 앱과 계산은 이 저장소와 브라우저 안에서
|
||
실행됩니다.
|
||
|
||
## 실행 환경
|
||
|
||
- Windows 10/11
|
||
- 최신 Microsoft Edge 또는 Google Chrome
|
||
- 저장소에 포함된 Windows PowerShell과 브라우저 외 추가 런타임 불필요
|
||
- WebGPU가 없거나 장치를 열 수 없어도 CPU backend로 실행 가능
|
||
|
||
## 가장 간단하게 시작하기
|
||
|
||
1. 저장소 최상위의 `start.cmd`를 더블클릭합니다.
|
||
2. 기본 브라우저에서 micarrsim 시작 화면이 열립니다.
|
||
3. 사용을 마치면 함께 열린 콘솔에서 `Ctrl+C`를 눌러 로컬 서버를 종료합니다.
|
||
|
||
브라우저가 자동으로 열리지 않으면 <http://127.0.0.1:4173/>을 직접 여세요. HTML module과
|
||
Worker를 사용하므로 `index.html` 파일을 탐색기에서 직접 열어서는 안 됩니다.
|
||
|
||
다른 포트를 쓰거나 브라우저를 자동으로 열지 않으려면 명령 프롬프트에서 실행합니다.
|
||
|
||
```bat
|
||
start.cmd -Port 4174 -NoBrowser
|
||
```
|
||
|
||
PowerShell에서 서버를 직접 실행할 수도 있습니다.
|
||
|
||
```powershell
|
||
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\scripts\serve.ps1 -Port 4174 -NoBrowser
|
||
```
|
||
|
||
이 명령의 `ExecutionPolicy Bypass`는 실행 중인 PowerShell 프로세스에만 적용되며 시스템 정책을
|
||
영구 변경하지 않습니다. 해당 명령을 사용했다면 <http://127.0.0.1:4174/>을 여세요.
|
||
|
||
실행 후 브라우저용 빠른 시작과 문제 해결은 <http://127.0.0.1:4173/docs/>에서도 볼 수 있습니다.
|
||
|
||
### 30초 기본 예제
|
||
|
||
1. 시작 화면에서 **Acoustic Camera**를 엽니다.
|
||
2. 기본 192채널 rectangular 배열, single-tone scene과 50×50 experiment가 준비될 때까지
|
||
기다립니다.
|
||
3. Snapshot 카드의 **▶ Snapshot 실행**을 누릅니다.
|
||
4. 계산이 끝나면 overlay와 평가 지표를 확인하고 **Result JSON**을 누릅니다.
|
||
|
||
실제 완료 시간은 브라우저와 장치에 따라 다릅니다. CPU fallback에서는 WebGPU보다 오래 걸릴 수
|
||
있습니다.
|
||
|
||
### 이동 음원 바로 보기
|
||
|
||
1. Acoustic Camera에서 **이동 예제 열기**를 누릅니다.
|
||
2. Moving 카드의 **Map 준비**를 눌러 2 Hz acoustic map을 계산합니다.
|
||
3. **재생**을 누르거나 시간 slider를 움직여 음원과 heatmap의 이동을 확인합니다.
|
||
|
||
이 기능은 trajectory가 있는 합성 Scene의 준정적 시간창 재생입니다. 실제 192채널 마이크 장치에서
|
||
들어오는 스트림을 캡처하는 기능은 아닙니다.
|
||
|
||
## 내 장면으로 전체 흐름 실행하기
|
||
|
||
### 1. Dataset Builder에서 Scene 만들기
|
||
|
||
1. 시작 화면에서 **Dataset Builder**를 엽니다.
|
||
2. 선택적으로 배경 이미지와 오디오를 추가합니다.
|
||
3. 녹음 파일은 **+ 오디오 파일 음원** 한 번으로 asset과 source를 함께 만들 수 있습니다. 합성
|
||
음원은 별도 버튼으로 추가합니다.
|
||
4. canvas 또는 x/y/z 입력으로 위치를 정하고 tone·noise·audio asset과 ambient를 설정합니다.
|
||
5. 움직이는 음원은 **시간에 따라 음원 이동**을 켜고 keyframe과 경로 미리보기 시간을 편집합니다.
|
||
6. 상태가 **저장 가능한 장면**이면 **Scene JSON 저장**을 누릅니다.
|
||
|
||
**Preview WAV 저장**은 source와 ambient를 공간 정보 없이 하나의 mono channel로 합친 청취
|
||
확인용 파일입니다. 192채널 마이크 신호나 beamforming 결과가 아닙니다.
|
||
|
||
### 2. Acoustic Camera에서 실행하기
|
||
|
||
1. 홈으로 돌아가 **Acoustic Camera**를 엽니다.
|
||
2. 다음 순서로 입력합니다: **Scene → Array → Experiment → Assets**.
|
||
3. **Scene**에서 Builder가 저장한 `.scene.json`을 선택합니다.
|
||
4. 기본 배열을 사용하지 않을 때만 **Array**에서 `.array.json`을 선택합니다.
|
||
5. 별도 실험 문서를 사용할 때만 **Experiment**에서 `.experiment.json`을 선택합니다.
|
||
6. Scene에 이미지나 audio asset이 있다면 **Assets**에서 Builder에 사용했던 원본 파일을 다시
|
||
선택합니다. 여러 파일을 한 번에 선택할 수 있습니다.
|
||
7. 입력 검증이 통과하면 backend와 scan grid를 정하고 실행합니다.
|
||
8. 완료 후 **Result JSON**을 저장합니다.
|
||
|
||
Array와 Scene을 먼저 불러와야 Experiment의 `arrayId`와 `sceneId` 관계를 안전하게 검증할 수
|
||
있습니다. Scene을 다시 불러오면 이전 asset 연결은 해제됩니다.
|
||
|
||
Camera에서 수정한 Scene·Experiment, 완료 Result와 전체 배열 비교 기록은 각각 JSON으로 저장할 수
|
||
있습니다. 저장하지 않은 항목이나 실행 중 계산이 있으면 페이지를 닫을 때 브라우저가 확인합니다.
|
||
|
||
## Scene JSON과 로컬 assets
|
||
|
||
Scene JSON에는 원본 이미지나 오디오 byte가 들어가지 않습니다. 대신 asset id, 종류, 파일명과
|
||
SHA-256 manifest를 저장합니다. 브라우저는 새 페이지나 세션에서 로컬 파일 접근 권한을 유지할 수
|
||
없으므로 원본 파일을 다시 선택해야 합니다.
|
||
|
||
- Camera는 SHA-256으로 선택한 파일을 manifest에 다시 연결합니다.
|
||
- 같은 이름이라도 내용이 달라 hash가 일치하지 않으면 거절합니다.
|
||
- 로컬 asset 한 파일은 최대 128 MiB, 연결된 파일 합계는 최대 512 MiB입니다.
|
||
- 실제 decode되어 메모리에 유지되는 오디오 합계는 최대 192 MiB입니다.
|
||
- Scene JSON에는 원본 파일명이 기록될 수 있으므로 파일을 외부에 공유하기 전에 확인하세요.
|
||
|
||
## Backend와 scan grid
|
||
|
||
- **Auto (GPU→CPU)**: 권장값입니다. WebGPU adapter나 device를 사용할 수 없거나 지원되는 장치
|
||
한계를 넘으면 CPU로 계속합니다.
|
||
- **WebGPU 강제**: GPU 경로만 사용합니다. 장치를 열 수 없거나 한계를 넘으면 fallback하지 않고
|
||
오류를 표시합니다.
|
||
- **CPU 강제**: 비교와 호환성 확인을 위해 CPU DAS만 사용합니다.
|
||
|
||
WebGPU 경로도 신호 합성과 STFT 일부는 CPU에서 수행합니다. grid의 point 수는 50×50을 1로 보면
|
||
100×100은 4배, 200×200은 16배입니다. 처음에는 50×50을 사용하고 해상도가 필요할 때만 높이세요.
|
||
실행 시간은 microphone 수, scene 길이, FFT, 대역 폭과 장치에 함께 좌우됩니다.
|
||
|
||
## 음향 환경과 마이크 응답
|
||
|
||
Camera의 **고급 설정**에서 자유음장, 흡음된 실내, 일반 실내와 반사 강한 실내를 선택할 수
|
||
있습니다. 실내 preset은 현재 Array·Scene·scan을 감싸는 shoebox room을 만들고 직접음에 다음의
|
||
희소 경로를 추가합니다.
|
||
|
||
- 여섯 면의 1차 image-source 반사와 결정적 scattering
|
||
- 축 정렬 occluder의 직접음 감쇠와 최단 corner 우회 회절
|
||
- RT60·gain·tap 수로 제한한 deterministic diffuse tail
|
||
|
||
각 마이크의 Array JSON에는 선택적 `frequencyResponse` 측정 curve를 넣을 수 있습니다.
|
||
합성기는 curve를 수신 채널에 적용하고, 기본 DAS는 알려진 curve를 역보정합니다. **마이크 주파수
|
||
응답 처리**를 보정하지 않음으로 바꾸면 같은 curve를 합성에만 적용해 robustness를 비교합니다.
|
||
응답 notch의 양의 역보정 boost는 기본 24 dB로 제한합니다.
|
||
필드, preset별 경로 예산과 물리적 한계는
|
||
[음향 환경과 마이크 응답 모델](docs/acoustic-model.md)에 정리되어 있습니다.
|
||
|
||
## 위치 추정, 빔 분포와 복수 음원
|
||
|
||
DAS 출력은 각 scan point의 상대 acoustic power map이며 위치 확률분포가 아닙니다. Camera는 map의
|
||
local peak를 위치 후보로 표시합니다. **빔 분포**를 켜면 각 peak의 연결된 half-power lobe에 대해
|
||
power 가중 공분산을 계산해 1× RMS 점선과 2× RMS 영역을 그립니다. Gaussian의 등고선처럼 보일 수
|
||
있지만 통계적으로 보정된 Gaussian, 신뢰구간 또는 발생 확률은 아닙니다.
|
||
|
||
복수 음원은 각각 별도 local peak가 남을 만큼 공간적으로 분리되고 선택 대역에 에너지가 있어야
|
||
검출됩니다. **Peak 검출 임계값 (%)**은 최강 peak 대비 후보의 최소 power입니다. 기본 25%에서 약한
|
||
두 번째 음원이 빠지면 10–20%로 낮출 수 있지만 sidelobe 오검출도 늘어납니다. 서로 같은 대역에서
|
||
main lobe보다 가깝거나 gain 차이가 큰 음원은 conventional DAS의 물리·알고리즘 한계 때문에
|
||
threshold만으로 분리되지 않을 수 있습니다.
|
||
|
||
## 이동 음원 라이브의 동작
|
||
|
||
Builder의 trajectory는 Scene 시작 기준 절대 시간의 keyframe 사이를 직선 보간합니다. Camera는
|
||
장면을 sample 경계에 맞춘 짧은 시간창으로 나누고, 각 창 중앙의 음원 위치에서 tone 위상, noise
|
||
index와 audio asset 재생 위치가 이어지도록 신호를 합성합니다. 계산된 map 사이에서는 heatmap을
|
||
보간하고 ground-truth 위치는 연속 보간합니다.
|
||
|
||
- Map rate: 초당 분석 map 목표 수. 높을수록 움직임이 세밀하지만 준비 시간이 늘 수 있습니다.
|
||
- 라이브 미리보기 상한: 48 maps, map당 최대 2,500 scan points
|
||
- 모델: 준정적 위치 변화이며 Doppler와 창 내부의 연속 전파 경로 변화는 포함하지 않음
|
||
- 실제 장치: 물리 192채널 capture/stream gateway는 하드웨어 형식이 정해진 뒤 별도 adapter가 필요
|
||
|
||
Scene 합성 없이 동기식 `Float32Array` 마이크 채널을 바로 처리하는
|
||
`createLocalizationPlan`, `localizeMultichannel`과 `StreamingDasLocalizer`가
|
||
`packages/acoustics-core`에 분리되어 있습니다. 고정 ring buffer, oldest-first drop,
|
||
반복 geometry·steering cache와 `AbortSignal` 취소를 제공하며 실제 capture 장치에는
|
||
channel/clock/transport adapter만 별도로 연결합니다. 실시간 여부는 각 결과의
|
||
`processingTimeMs <= deadlineMs`와 누적 `deadlineMisses`·`droppedSamples`로
|
||
해당 장치에서 확인합니다. 복사할 파일과 운용 계약은
|
||
[실측 다채널 위치추정 코어 포팅](docs/realtime-porting.md)을 참고하세요.
|
||
|
||
## Result JSON
|
||
|
||
Result JSON은 계약 버전 `1.0.0`의 `micarrsim.result` 문서입니다. 주요 내용은 다음과 같습니다.
|
||
|
||
- 실행한 `experimentId`, `arrayId`, `sceneId`, 실제 `backend`와 생성 시각
|
||
- Array·Scene·Experiment의 canonical SHA-256인 `inputHash`
|
||
- 정규화 전 peak, 적용 scale, clipping 수와 음향 모델·희소 경로 수를 담은 `signalStats`
|
||
- 전체·신호 생성·beamforming 시간인 `timingMs`
|
||
- 주파수 대역별 선형 power `rawMap`, 표시용 `displayMap`, 검출 `peaks`
|
||
- 위치 오차, precision/recall, truth 반경 내 energy, peak-to-sidelobe, main-lobe 폭을 계산하기
|
||
위한 평가 파라미터와 `metrics`
|
||
- peak별 half-power 공분산과 RMS ellipse를 담은 `beamSpread` (`calibrated: false`)
|
||
|
||
평가에서 tone source는 tone 주파수가 포함되는 band의 ground truth로만 사용합니다. Audio asset과
|
||
noise source는 스펙트럼을 미리 알 수 없으므로 모든 band의 ground truth로 취급합니다. 이 가정은
|
||
결과를 실제 데이터와 해석할 때 고려해야 합니다.
|
||
|
||
## 개인정보와 모델의 한계
|
||
|
||
서버는 `127.0.0.1` loopback에만 열리고 외부 서비스로 파일을 업로드하거나 telemetry를 보내지
|
||
않습니다. 선택한 파일은 브라우저 메모리에서 읽으며 생성한 JSON/WAV는 브라우저 다운로드로만
|
||
저장됩니다.
|
||
|
||
음향 모델은 직접 경로의 자유음장과 1차 반사·scattering·occluder 회절·RT60 tail을 제한된
|
||
경로로 계산하는 shoebox 근사를 제공합니다. 파동 방정식, 고차 반사, 재질별 주파수 의존 흡음,
|
||
복잡한 mesh 회절, 바람, Doppler, 마이크 self-noise·비선형, ADC와 channel clock은 모델링하지
|
||
않습니다. Beamformer는 conventional DAS이며 UI의 DAMAS와 CLEAN-SC는 아직 사용할 수 없습니다.
|
||
따라서 결과는 배열·grid·대역의 상대 비교와 소프트웨어 검증용이며, 현장 성능 인증이나 안전
|
||
판단을 대신하지 않습니다.
|
||
|
||
## 배열 예제
|
||
|
||
- `assets/array-geometries/rectangular-16x12.array.json`: 0.45 m 정사각 aperture의 16×12 기준 배열
|
||
- `assets/array-geometries/fermat-spiral-192.array.json`: 0.45 m 원형 aperture의 192채널 Fermat spiral
|
||
|
||
Camera의 **비교 배열** 선택으로 두 fixture를 같은 scene과 experiment에서 연속 실행할 수 있습니다.
|
||
상세한 생성법은 [`assets/array-geometries/README.md`](assets/array-geometries/README.md)를 참고하세요.
|
||
|
||
## 테스트와 benchmark
|
||
|
||
최상위 폴더에서 자동 서버·headless 브라우저·정리까지 한 번에 실행하려면 다음을 사용합니다.
|
||
|
||
```bat
|
||
test.cmd
|
||
```
|
||
|
||
서버를 실행한 뒤 다음 주소를 브라우저에서 엽니다.
|
||
|
||
- 전체 browser test runner: <http://127.0.0.1:4173/tests/>
|
||
- WebGPU scaling benchmark: <http://127.0.0.1:4173/benchmarks/webgpu-scaling.html>
|
||
|
||
포트를 바꿨다면 URL의 포트도 같은 값으로 바꾸세요. 테스트 범위는
|
||
[`tests/unit/README.md`](tests/unit/README.md)와
|
||
[`tests/integration/README.md`](tests/integration/README.md), 기준 실측은
|
||
[`docs/benchmarks/README.md`](docs/benchmarks/README.md)에 설명되어 있습니다.
|
||
|
||
## 저장 형식과 개발 문서
|
||
|
||
- [`docs/data-contracts.md`](docs/data-contracts.md): Array·Scene·Experiment·Result 계약
|
||
- [`docs/acoustic-model.md`](docs/acoustic-model.md): 마이크 응답과 자유음장·shoebox 희소 근사
|
||
- [`docs/realtime-porting.md`](docs/realtime-porting.md): 실측 다채널 위치추정 API 포팅
|
||
- [`schemas/README.md`](schemas/README.md): JSON Schema 구성
|
||
- [`docs/execution-plan.md`](docs/execution-plan.md): 구현 단계와 기술 결정
|
||
- [`goal.md`](goal.md): 프로젝트 목표
|
||
|
||
원본 DCASE/MIMII 데이터, 사용자가 선택한 assets와 생성된 대용량 결과는 저장소에 커밋하지
|
||
않습니다.
|
||
|
||
## 디렉터리 구조
|
||
|
||
```text
|
||
apps/ Dataset Builder와 Acoustic Camera UI
|
||
assets/ 192채널 배열과 synthetic Scene/Experiment fixture
|
||
benchmarks/ 현재 브라우저에서 실행하는 WebGPU scaling 측정
|
||
docs/ 사용자 안내, 데이터 계약, 실행 계획과 기준 실측
|
||
packages/ 음향 수치 모델, 계약 검증, UI, WebGPU kernel
|
||
schemas/ Array·Scene·Experiment·Result JSON Schema
|
||
scripts/ 무설치 로컬 서버와 fixture 생성기
|
||
tests/ 브라우저 unit·integration·end-to-end test
|
||
start.cmd Windows 원클릭 실행 진입점
|
||
```
|