docs: explain localization choices and cost
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
# micarrsim
|
# micarrsim
|
||||||
|
|
||||||
192채널 MEMS 마이크 배열의 배치와 자유음장·저비용 실내 근사에서의 DAS 음향 영상을 비교하는 로컬 브라우저
|
192채널 MEMS 마이크 배열의 배치와 자유음장·저비용 실내 근사에서 DAS·DAS-PHAT·GCC-PHAT
|
||||||
|
위치 추정을 비교하는 로컬 브라우저
|
||||||
시뮬레이터입니다. Dataset Builder에서 녹음 파일·합성 신호와 이동 경로를 포함한 재현 가능한
|
시뮬레이터입니다. Dataset Builder에서 녹음 파일·합성 신호와 이동 경로를 포함한 재현 가능한
|
||||||
음향 장면을 만들고 Acoustic Camera에서 CPU 또는 WebGPU로 배열 응답, acoustic map과 위치 검출
|
음향 장면을 만들고 Acoustic Camera에서 CPU 또는 WebGPU로 배열 응답, acoustic map과 위치 검출
|
||||||
지표를 계산하거나 이동 장면을 시간축으로 재생합니다.
|
지표를 계산하거나 이동 장면을 시간축으로 재생합니다.
|
||||||
@@ -46,9 +47,12 @@ powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\scripts\serve.
|
|||||||
1. 시작 화면에서 **Acoustic Camera**를 엽니다.
|
1. 시작 화면에서 **Acoustic Camera**를 엽니다.
|
||||||
2. 기본 192채널 rectangular 배열, single-tone scene과 50×50 experiment가 준비될 때까지
|
2. 기본 192채널 rectangular 배열, single-tone scene과 50×50 experiment가 준비될 때까지
|
||||||
기다립니다.
|
기다립니다.
|
||||||
3. Snapshot 카드의 **▶ Snapshot 실행**을 누릅니다.
|
3. 처음에는 **DAS · 기준 power**를 두고 Snapshot 카드의 **▶ Snapshot 실행**을 누릅니다.
|
||||||
4. 계산이 끝나면 overlay와 평가 지표를 확인하고 **Result JSON**을 누릅니다.
|
4. 계산이 끝나면 overlay와 평가 지표를 확인하고 **Result JSON**을 누릅니다.
|
||||||
|
|
||||||
|
같은 입력에서 **위치 추정 알고리즘**만 DAS-PHAT으로 바꿔 다시 실행하면 아래 비교 기록에 두 결과가
|
||||||
|
나란히 남습니다. GCC-PHAT은 광대역 입력에서 비교하세요.
|
||||||
|
|
||||||
실제 완료 시간은 브라우저와 장치에 따라 다릅니다. CPU fallback에서는 WebGPU보다 오래 걸릴 수
|
실제 완료 시간은 브라우저와 장치에 따라 다릅니다. CPU fallback에서는 WebGPU보다 오래 걸릴 수
|
||||||
있습니다.
|
있습니다.
|
||||||
|
|
||||||
@@ -85,7 +89,7 @@ powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\scripts\serve.
|
|||||||
5. 별도 실험 문서를 사용할 때만 **Experiment**에서 `.experiment.json`을 선택합니다.
|
5. 별도 실험 문서를 사용할 때만 **Experiment**에서 `.experiment.json`을 선택합니다.
|
||||||
6. Scene에 이미지나 audio asset이 있다면 **Assets**에서 Builder에 사용했던 원본 파일을 다시
|
6. Scene에 이미지나 audio asset이 있다면 **Assets**에서 Builder에 사용했던 원본 파일을 다시
|
||||||
선택합니다. 여러 파일을 한 번에 선택할 수 있습니다.
|
선택합니다. 여러 파일을 한 번에 선택할 수 있습니다.
|
||||||
7. 입력 검증이 통과하면 backend와 scan grid를 정하고 실행합니다.
|
7. 입력 검증이 통과하면 위치 추정 알고리즘, backend와 scan grid를 정하고 실행합니다.
|
||||||
8. 완료 후 **Result JSON**을 저장합니다.
|
8. 완료 후 **Result JSON**을 저장합니다.
|
||||||
|
|
||||||
Array와 Scene을 먼저 불러와야 Experiment의 `arrayId`와 `sceneId` 관계를 안전하게 검증할 수
|
Array와 Scene을 먼저 불러와야 Experiment의 `arrayId`와 `sceneId` 관계를 안전하게 검증할 수
|
||||||
@@ -106,18 +110,38 @@ SHA-256 manifest를 저장합니다. 브라우저는 새 페이지나 세션에
|
|||||||
- 실제 decode되어 메모리에 유지되는 오디오 합계는 최대 192 MiB입니다.
|
- 실제 decode되어 메모리에 유지되는 오디오 합계는 최대 192 MiB입니다.
|
||||||
- Scene JSON에는 원본 파일명이 기록될 수 있으므로 파일을 외부에 공유하기 전에 확인하세요.
|
- Scene JSON에는 원본 파일명이 기록될 수 있으므로 파일을 외부에 공유하기 전에 확인하세요.
|
||||||
|
|
||||||
## Backend와 scan grid
|
## 알고리즘, Backend와 계산량
|
||||||
|
|
||||||
|
| 알고리즘 | 원시 map | backend | 용도와 주의점 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| DAS | 상대 acoustic power | CPU, WebGPU | 가장 단순한 기준선. 채널 gain과 알려진 마이크 응답을 보정합니다. |
|
||||||
|
| DAS-PHAT | 무차원 score | CPU, WebGPU | 마이크별 진폭을 버리고 위상 정합을 비교해 gain·반사에 더 강건할 수 있습니다. |
|
||||||
|
| GCC-PHAT | 무차원 score | CPU | 한 reference와 나머지 마이크의 TDOA 상관을 사용합니다. 광대역이 필요하며 협대역에서는 주기적 모호성이 큽니다. |
|
||||||
|
|
||||||
- **Auto (GPU→CPU)**: 권장값입니다. WebGPU adapter나 device를 사용할 수 없거나 지원되는 장치
|
- **Auto (GPU→CPU)**: 권장값입니다. WebGPU adapter나 device를 사용할 수 없거나 지원되는 장치
|
||||||
한계를 넘으면 CPU로 계속합니다.
|
한계를 넘으면 CPU로 계속합니다.
|
||||||
- **WebGPU 강제**: GPU 경로만 사용합니다. 장치를 열 수 없거나 한계를 넘으면 fallback하지 않고
|
- **WebGPU 강제**: GPU 경로만 사용합니다. 장치를 열 수 없거나 한계를 넘으면 fallback하지 않고
|
||||||
오류를 표시합니다.
|
오류를 표시합니다.
|
||||||
- **CPU 강제**: 비교와 호환성 확인을 위해 CPU DAS만 사용합니다.
|
- **CPU 강제**: 비교와 호환성 확인을 위해 선택한 알고리즘의 CPU 구현을 사용합니다.
|
||||||
|
|
||||||
|
GCC-PHAT은 현재 CPU 전용이므로 선택하면 Auto 또는 CPU만 사용할 수 있습니다. Camera는 각 band가
|
||||||
|
8개 미만의 FFT bin을 포함하면 협대역 경고를 표시합니다.
|
||||||
|
|
||||||
WebGPU 경로도 신호 합성과 STFT 일부는 CPU에서 수행합니다. grid의 point 수는 50×50을 1로 보면
|
WebGPU 경로도 신호 합성과 STFT 일부는 CPU에서 수행합니다. grid의 point 수는 50×50을 1로 보면
|
||||||
100×100은 4배, 200×200은 16배입니다. 처음에는 50×50을 사용하고 해상도가 필요할 때만 높이세요.
|
100×100은 4배, 200×200은 16배입니다. 처음에는 50×50을 사용하고 해상도가 필요할 때만 높이세요.
|
||||||
실행 시간은 microphone 수, scene 길이, FFT, 대역 폭과 장치에 함께 좌우됩니다.
|
실행 시간은 microphone 수, scene 길이, FFT, 대역 폭과 장치에 함께 좌우됩니다.
|
||||||
|
|
||||||
|
DAS 계열의 scan 주항은 `P × M × T × F`입니다. 192채널·50×50·46 frames·2 bins의 기존
|
||||||
|
fixture는 44,160,000 complex MAC입니다. GCC-PHAT은 같은 조건에서 forward STFT를 그대로
|
||||||
|
수행한 뒤 191 reference pairs에 대해 35,144회의 2-pass cross-spectrum 연산, 191회의 inverse
|
||||||
|
FFT와 477,500회의 point/pair lookup을 수행합니다. 따라서 큰 grid·광대역에서는 scan 비용을
|
||||||
|
줄이지만 작은 grid에서는 공통 STFT 때문에 전체 시간이 같은 비율로 줄지는 않습니다.
|
||||||
|
|
||||||
|
저장된 Intel Gen9 측정에서 DAS 50×50의 GPU wall은 79.2 ms였지만 CPU STFT는 1,669.8 ms,
|
||||||
|
signal 합성은 별도 1,200.5 ms였습니다. 즉 현재 기본 fixture의 병목은 단순히 grid scan 하나가
|
||||||
|
아닙니다. Camera의 workload 줄은 STFT, DAS MAC 또는 GCC cross-spectrum·inverse FFT·lookup,
|
||||||
|
signal path와 distance cache를 따로 표시합니다.
|
||||||
|
|
||||||
## 음향 환경과 마이크 응답
|
## 음향 환경과 마이크 응답
|
||||||
|
|
||||||
Camera의 **고급 설정**에서 자유음장, 흡음된 실내, 일반 실내와 반사 강한 실내를 선택할 수
|
Camera의 **고급 설정**에서 자유음장, 흡음된 실내, 일반 실내와 반사 강한 실내를 선택할 수
|
||||||
@@ -137,13 +161,18 @@ Camera의 **고급 설정**에서 자유음장, 흡음된 실내, 일반 실내
|
|||||||
|
|
||||||
## 위치 추정, 빔 분포와 복수 음원
|
## 위치 추정, 빔 분포와 복수 음원
|
||||||
|
|
||||||
DAS 출력은 각 scan point의 상대 acoustic power map이며 위치 확률분포가 아닙니다. Camera는 map의
|
DAS 출력은 각 scan point의 상대 acoustic power, PHAT 계열 출력은 무차원 score이며 어느 쪽도
|
||||||
local peak를 위치 후보로 표시합니다. **빔 분포**를 켜면 각 peak의 연결된 half-power lobe에 대해
|
위치 확률분포가 아닙니다. Camera는 map의 local peak를 위치 후보로 표시합니다. **빔 분포**를 켜면
|
||||||
power 가중 공분산을 계산해 1× RMS 점선과 2× RMS 영역을 그립니다. Gaussian의 등고선처럼 보일 수
|
각 peak의 연결된 half-maximum lobe에 대해 map 값 가중 공분산을 계산해 1× RMS 점선과 2× RMS
|
||||||
있지만 통계적으로 보정된 Gaussian, 신뢰구간 또는 발생 확률은 아닙니다.
|
영역을 그립니다. Gaussian의 등고선처럼 보일 수 있지만 통계적으로 보정된 Gaussian, 신뢰구간 또는
|
||||||
|
발생 확률은 아닙니다.
|
||||||
|
|
||||||
|
GCC-PHAT raw score는 pair 수·band coefficient 수·IFFT 크기로 정규화한 0–1 양의 상관 응답입니다.
|
||||||
|
scan 범위나 마이크 수 때문에 값이 단순히 커지는 현상은 막지만, 0.8을 “위치 확률 80%”로 읽을 수는
|
||||||
|
없고 다른 알고리즘의 score와 절대값을 비교해서도 안 됩니다.
|
||||||
|
|
||||||
복수 음원은 각각 별도 local peak가 남을 만큼 공간적으로 분리되고 선택 대역에 에너지가 있어야
|
복수 음원은 각각 별도 local peak가 남을 만큼 공간적으로 분리되고 선택 대역에 에너지가 있어야
|
||||||
검출됩니다. **Peak 검출 임계값 (%)**은 최강 peak 대비 후보의 최소 power입니다. 기본 25%에서 약한
|
검출됩니다. **Peak 검출 임계값 (%)**은 최강 peak 대비 후보의 최소 map 값입니다. 기본 25%에서 약한
|
||||||
두 번째 음원이 빠지면 10–20%로 낮출 수 있지만 sidelobe 오검출도 늘어납니다. 서로 같은 대역에서
|
두 번째 음원이 빠지면 10–20%로 낮출 수 있지만 sidelobe 오검출도 늘어납니다. 서로 같은 대역에서
|
||||||
main lobe보다 가깝거나 gain 차이가 큰 음원은 conventional DAS의 물리·알고리즘 한계 때문에
|
main lobe보다 가깝거나 gain 차이가 큰 음원은 conventional DAS의 물리·알고리즘 한계 때문에
|
||||||
threshold만으로 분리되지 않을 수 있습니다.
|
threshold만으로 분리되지 않을 수 있습니다.
|
||||||
@@ -161,9 +190,9 @@ index와 audio asset 재생 위치가 이어지도록 신호를 합성합니다.
|
|||||||
- 실제 장치: 물리 192채널 capture/stream gateway는 하드웨어 형식이 정해진 뒤 별도 adapter가 필요
|
- 실제 장치: 물리 192채널 capture/stream gateway는 하드웨어 형식이 정해진 뒤 별도 adapter가 필요
|
||||||
|
|
||||||
Scene 합성 없이 동기식 `Float32Array` 마이크 채널을 바로 처리하는
|
Scene 합성 없이 동기식 `Float32Array` 마이크 채널을 바로 처리하는
|
||||||
`createLocalizationPlan`, `localizeMultichannel`과 `StreamingDasLocalizer`가
|
`createLocalizationPlan`, `localizeMultichannel`과 `StreamingLocalizer`가
|
||||||
`packages/acoustics-core`에 분리되어 있습니다. 고정 ring buffer, oldest-first drop,
|
`packages/acoustics-core`에 분리되어 있습니다. 고정 ring buffer, oldest-first drop,
|
||||||
반복 geometry·steering cache와 `AbortSignal` 취소를 제공하며 실제 capture 장치에는
|
반복 geometry·workspace cache와 `AbortSignal` 취소를 제공하며 실제 capture 장치에는
|
||||||
channel/clock/transport adapter만 별도로 연결합니다. 실시간 여부는 각 결과의
|
channel/clock/transport adapter만 별도로 연결합니다. 실시간 여부는 각 결과의
|
||||||
`processingTimeMs <= deadlineMs`와 누적 `deadlineMisses`·`droppedSamples`로
|
`processingTimeMs <= deadlineMs`와 누적 `deadlineMisses`·`droppedSamples`로
|
||||||
해당 장치에서 확인합니다. 복사할 파일과 운용 계약은
|
해당 장치에서 확인합니다. 복사할 파일과 운용 계약은
|
||||||
@@ -173,11 +202,11 @@ channel/clock/transport adapter만 별도로 연결합니다. 실시간 여부
|
|||||||
|
|
||||||
Result JSON은 계약 버전 `1.0.0`의 `micarrsim.result` 문서입니다. 주요 내용은 다음과 같습니다.
|
Result JSON은 계약 버전 `1.0.0`의 `micarrsim.result` 문서입니다. 주요 내용은 다음과 같습니다.
|
||||||
|
|
||||||
- 실행한 `experimentId`, `arrayId`, `sceneId`, 실제 `backend`와 생성 시각
|
- 실행한 `experimentId`, `arrayId`, `sceneId`, 실제 `algorithm`·`backend`와 생성 시각
|
||||||
- Array·Scene·Experiment의 canonical SHA-256인 `inputHash`
|
- Array·Scene·Experiment의 canonical SHA-256인 `inputHash`
|
||||||
- 정규화 전 peak, 적용 scale, clipping 수와 음향 모델·희소 경로 수를 담은 `signalStats`
|
- 정규화 전 peak, 적용 scale, clipping 수와 음향 모델·희소 경로 수를 담은 `signalStats`
|
||||||
- 전체·신호 생성·beamforming 시간인 `timingMs`
|
- 전체·신호 생성·위치 추정 시간인 `timingMs.localization`과 기존 reader용 `beamforming` alias
|
||||||
- 주파수 대역별 선형 power `rawMap`, 표시용 `displayMap`, 검출 `peaks`
|
- 주파수 대역별 power 또는 score `rawMap`, 표시용 `displayMap`, 검출 `peaks`
|
||||||
- 위치 오차, precision/recall, truth 반경 내 energy, peak-to-sidelobe, main-lobe 폭을 계산하기
|
- 위치 오차, precision/recall, truth 반경 내 energy, peak-to-sidelobe, main-lobe 폭을 계산하기
|
||||||
위한 평가 파라미터와 `metrics`
|
위한 평가 파라미터와 `metrics`
|
||||||
- peak별 half-power 공분산과 RMS ellipse를 담은 `beamSpread` (`calibrated: false`)
|
- peak별 half-power 공분산과 RMS ellipse를 담은 `beamSpread` (`calibrated: false`)
|
||||||
@@ -195,7 +224,8 @@ noise source는 스펙트럼을 미리 알 수 없으므로 모든 band의 groun
|
|||||||
음향 모델은 직접 경로의 자유음장과 1차 반사·scattering·occluder 회절·RT60 tail을 제한된
|
음향 모델은 직접 경로의 자유음장과 1차 반사·scattering·occluder 회절·RT60 tail을 제한된
|
||||||
경로로 계산하는 shoebox 근사를 제공합니다. 파동 방정식, 고차 반사, 재질별 주파수 의존 흡음,
|
경로로 계산하는 shoebox 근사를 제공합니다. 파동 방정식, 고차 반사, 재질별 주파수 의존 흡음,
|
||||||
복잡한 mesh 회절, 바람, Doppler, 마이크 self-noise·비선형, ADC와 channel clock은 모델링하지
|
복잡한 mesh 회절, 바람, Doppler, 마이크 self-noise·비선형, ADC와 channel clock은 모델링하지
|
||||||
않습니다. Beamformer는 conventional DAS이며 UI의 DAMAS와 CLEAN-SC는 아직 사용할 수 없습니다.
|
않습니다. 위치 추정기는 DAS, DAS-PHAT와 CPU GCC-PHAT를 제공하지만 full-pair SRP-PHAT, MUSIC,
|
||||||
|
DAMAS와 CLEAN-SC는 구현하지 않습니다.
|
||||||
따라서 결과는 배열·grid·대역의 상대 비교와 소프트웨어 검증용이며, 현장 성능 인증이나 안전
|
따라서 결과는 배열·grid·대역의 상대 비교와 소프트웨어 검증용이며, 현장 성능 인증이나 안전
|
||||||
판단을 대신하지 않습니다.
|
판단을 대신하지 않습니다.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Acoustic Camera
|
# Acoustic Camera
|
||||||
|
|
||||||
Scene과 마이크 배열로 자유음장 또는 저비용 shoebox microphone signal을 합성하고, STFT와
|
Scene과 마이크 배열로 자유음장 또는 저비용 shoebox microphone signal을 합성하고, STFT와
|
||||||
conventional DAS를 통해 주파수 대역별 acoustic map과 ground-truth 평가 지표를 만드는 브라우저
|
DAS·DAS-PHAT·GCC-PHAT 위치추정으로 주파수 대역별 acoustic map과 ground-truth 평가 지표를
|
||||||
앱입니다. 정지 장면은 Snapshot, trajectory 장면은 Moving 흐름으로 분리되어 있습니다.
|
만드는 브라우저 앱입니다. 정지 장면은 Snapshot, trajectory 장면은 Moving 흐름으로 분리되어
|
||||||
|
있습니다.
|
||||||
|
|
||||||
## 열기와 Snapshot
|
## 열기와 Snapshot
|
||||||
|
|
||||||
@@ -42,12 +43,31 @@ Camera가 SHA-256을 계산해 manifest에 연결합니다. 같은 이름이라
|
|||||||
|
|
||||||
파일은 외부로 업로드되지 않고 브라우저 메모리에서만 처리됩니다.
|
파일은 외부로 업로드되지 않고 브라우저 메모리에서만 처리됩니다.
|
||||||
|
|
||||||
## Backend 선택
|
## 위치 추정 알고리즘과 Backend
|
||||||
|
|
||||||
|
**분석 설정 → 위치 추정 알고리즘**에서 다음 세 구현을 선택합니다.
|
||||||
|
|
||||||
|
- **DAS**: 채널 진폭과 위상을 유지해 coherent sum power를 계산하는 기준선입니다. CPU와 WebGPU를
|
||||||
|
지원하고 `rawMap.scale`은 `power`입니다.
|
||||||
|
- **DAS-PHAT**: 각 STFT 성분의 크기를 정규화하고 위상을 합산합니다. 채널 gain 차이에 덜
|
||||||
|
민감한 비교용이며 CPU와 WebGPU를 지원합니다. 결과는 무차원 `score`입니다.
|
||||||
|
- **GCC-PHAT**: 기준 마이크와 나머지 마이크의 PHAT 상관에서 기하학적 TDOA를 평가합니다. 현재
|
||||||
|
CPU 전용이므로 Auto는 CPU를 선택하고 **WebGPU 강제**는 선택할 수 없습니다. 각 band가 8개
|
||||||
|
미만의 FFT bin을 포함하면 협대역 상관이 불안정할 수 있다는 경고가 표시됩니다.
|
||||||
|
|
||||||
|
PHAT score는 위치 확률이나 음향 power가 아닙니다. 세 알고리즘 모두 같은 scan grid에 응답 map을
|
||||||
|
만들지만, 진폭 보존 여부와 실패 양상이 다르므로 같은 Scene·Array·band로 비교하세요.
|
||||||
|
GCC-PHAT raw score는 pair·band coefficient·IFFT 크기를 정규화한 0–1 양의 상관 응답이라 scan
|
||||||
|
범위나 마이크 수에 따른 단순 scale 변화는 피하지만, 확률이나 다른 알고리즘과 공통인 confidence는
|
||||||
|
아닙니다.
|
||||||
|
|
||||||
- **Auto (GPU→CPU)**: 권장. WebGPU를 먼저 시도하고 adapter/device 부재나 지원되는 장치 한계가
|
- **Auto (GPU→CPU)**: 권장. WebGPU를 먼저 시도하고 adapter/device 부재나 지원되는 장치 한계가
|
||||||
있으면 CPU로 계속합니다.
|
있으면 CPU로 계속합니다. 라이브 준비에서는 첫 fallback 뒤 남은 frame이 같은 CPU analysis
|
||||||
- **WebGPU 강제**: GPU만 사용하며 운용 오류가 나도 CPU로 fallback하지 않습니다.
|
plan을 재사용하므로 GPU 실패를 매 frame 반복하지 않습니다. GCC-PHAT에서는 **Auto (CPU)**로
|
||||||
- **CPU 강제**: CPU 수치 기준이나 WebGPU가 없는 환경에서 사용합니다.
|
표시됩니다.
|
||||||
|
- **WebGPU 강제**: DAS와 DAS-PHAT를 GPU에서만 실행하며 운용 오류가 나도 CPU로 fallback하지
|
||||||
|
않습니다.
|
||||||
|
- **CPU 강제**: 선택한 알고리즘의 CPU 수치 기준이나 WebGPU가 없는 환경에서 사용합니다.
|
||||||
|
|
||||||
WebGPU가 감지돼도 실제 장치는 실행 시 확인합니다. 계산 중 **계산 취소**를 누르면 Worker를
|
WebGPU가 감지돼도 실제 장치는 실행 시 확인합니다. 계산 중 **계산 취소**를 누르면 Worker를
|
||||||
종료하며, 이미 완료된 이전 결과가 있으면 그대로 남습니다.
|
종료하며, 이미 완료된 이전 결과가 있으면 그대로 남습니다.
|
||||||
@@ -82,9 +102,10 @@ Array의 각 microphone에는 선택적 `frequencyResponse`를 넣을 수 있습
|
|||||||
```
|
```
|
||||||
|
|
||||||
curve는 합성 microphone channel에 항상 적용됩니다. **마이크 주파수 응답 처리**의 기본
|
curve는 합성 microphone channel에 항상 적용됩니다. **마이크 주파수 응답 처리**의 기본
|
||||||
**측정 curve 적용 + 위치추정에서 역보정**은 CPU와 WebGPU DAS에서 알려진 gain/phase를
|
**측정 curve 적용 + 위치추정에서 역보정**은 선택한 CPU 위치추정과 DAS/DAS-PHAT WebGPU
|
||||||
역보정합니다. **측정 curve 적용 + 보정하지 않음**은 합성 응답은 유지하고 역보정만 꺼서 영향을
|
경로에서 알려진 gain/phase를 역보정합니다. **측정 curve 적용 + 보정하지 않음**은 합성 응답은
|
||||||
비교합니다. curve가 없는 마이크는 기존 결과를 유지합니다. 응답 notch를 과도하게 증폭하지
|
유지하고 역보정만 꺼서 영향을 비교합니다. curve가 없는 마이크는 기존 결과를 유지합니다. 응답 notch를
|
||||||
|
과도하게 증폭하지
|
||||||
않도록 역보정의 양의 gain boost는 기본 24 dB로 제한하며, 사용자 Experiment JSON의
|
않도록 역보정의 양의 gain boost는 기본 24 dB로 제한하며, 사용자 Experiment JSON의
|
||||||
`beamforming.maxCompensationDb`에서 0–120 dB로 지정할 수 있습니다.
|
`beamforming.maxCompensationDb`에서 0–120 dB로 지정할 수 있습니다.
|
||||||
|
|
||||||
@@ -94,32 +115,40 @@ curve는 합성 microphone channel에 항상 적용됩니다. **마이크 주파
|
|||||||
## Grid, STFT와 대역
|
## Grid, STFT와 대역
|
||||||
|
|
||||||
50×50은 2,500 points입니다. 이를 1로 보면 100×100은 4배, 200×200은 16배 points를 계산합니다.
|
50×50은 2,500 points입니다. 이를 1로 보면 100×100은 4배, 200×200은 16배 points를 계산합니다.
|
||||||
처음에는 50×50을 권장합니다. 실행량은 microphone 수, scene 길이, FFT/hop과 선택 band의 bin
|
처음에는 50×50을 권장합니다. 연산량 줄에는 공통 STFT transform 수와 signal path, distance
|
||||||
수에도 비례하므로 실제 시간 배율은 장치마다 다릅니다.
|
cache를 표시하고 알고리즘별 위치추정 비용을 다음처럼 분리합니다.
|
||||||
|
|
||||||
|
- DAS/DAS-PHAT: scan point × microphone × STFT frame × 선택 bin의 complex MAC
|
||||||
|
- GCC-PHAT: 기준 마이크 pair별 two-pass cross-spectrum, pair × band inverse FFT와
|
||||||
|
scan point × pair × band correlation lookup
|
||||||
|
|
||||||
|
이는 구현 연산 횟수이지 실행 시간 예측값은 아닙니다. scene 길이, microphone 수, FFT/hop,
|
||||||
|
band 수와 폭, grid 및 CPU/GPU에 따라 실제 시간이 달라집니다.
|
||||||
|
|
||||||
각 band는 id, 최소/최대 Hz와 overlay 색을 가집니다. Nyquist를 넘거나 겹치는 id 등 계약 오류는
|
각 band는 id, 최소/최대 Hz와 overlay 색을 가집니다. Nyquist를 넘거나 겹치는 id 등 계약 오류는
|
||||||
실행 전에 표시됩니다. 현재 후처리는 raw DAS만 지원하며 DAMAS와 CLEAN-SC 항목은 비활성화되어
|
실행 전에 표시됩니다. DAMAS와 CLEAN-SC 후처리는 아직 구현하지 않았으며, 실행할 수 없는 비활성
|
||||||
있습니다.
|
항목은 Camera UI에서 제거했습니다. Result의 `processedMaps` 계약만 향후 확장을 위해 남아 있습니다.
|
||||||
|
|
||||||
**Peak 검출 임계값 (%)**은 최강 local peak의 power에 대한 상대 임계값이며 Experiment JSON에
|
**Peak 검출 임계값 (%)**은 최강 local peak의 map 값에 대한 상대 임계값이며 Experiment JSON에
|
||||||
저장됩니다. 기본 25%에서 약한 두 번째 음원이 빠지면 10–20%로 낮추세요. 낮은 값은 더 약한 후보를
|
저장됩니다. 기본 25%에서 약한 두 번째 음원이 빠지면 10–20%로 낮추세요. 낮은 값은 더 약한 후보를
|
||||||
살리는 대신 sidelobe를 음원으로 잘못 고를 가능성도 높입니다. 같은 대역의 두 음원이 main lobe
|
살리는 대신 sidelobe를 음원으로 잘못 고를 가능성도 높입니다. 같은 대역의 두 음원이 알고리즘의
|
||||||
폭보다 가깝다면 grid만 키우거나 threshold를 낮춰도 conventional DAS map에서 하나로 합쳐질 수
|
main lobe 폭보다 가깝다면 grid만 키우거나 threshold를 낮춰도 하나로 합쳐질 수 있습니다.
|
||||||
있습니다.
|
|
||||||
|
|
||||||
## 화면과 배열 비교
|
## 화면과 배열·알고리즘 비교
|
||||||
|
|
||||||
- acoustic overlay의 투명도와 표시할 band를 선택할 수 있습니다.
|
- acoustic overlay의 투명도와 표시할 band를 선택할 수 있습니다.
|
||||||
- **Ground truth**를 켜면 source 위치와 검출 peak를 비교할 수 있습니다.
|
- **Ground truth**를 켜면 source 위치와 검출 peak를 비교할 수 있습니다.
|
||||||
- **빔 분포**는 peak 주변 half-power lobe의 power 가중 공분산을 1× RMS 점선과 2× RMS 영역으로
|
- **빔 분포**는 DAS power의 half-power 또는 PHAT score의 half-maximum 연결 성분을 해당 map
|
||||||
표시합니다. 위치 확률, Gaussian 신뢰구간 또는 측정 불확실성 보정값은 아닙니다.
|
값으로 가중한 공분산으로 계산해 1× RMS 점선과 2× RMS 영역으로 표시합니다. 위치 확률,
|
||||||
|
Gaussian 신뢰구간 또는 측정 불확실성 보정값은 아닙니다.
|
||||||
- **배열 선택**에는 채널 수(4·12·48·192·384), aperture 크기(0.12·0.45·1.20 m), rectangular와
|
- **배열 선택**에는 채널 수(4·12·48·192·384), aperture 크기(0.12·0.45·1.20 m), rectangular와
|
||||||
Fermat spiral 배치를 분리 비교하는 8개 preset이 있습니다. 같은 Scene/Experiment에서 연속 실행하면
|
Fermat spiral 배치를 분리 비교하는 8개 preset이 있습니다. 같은 scene·scan·STFT에서 연속
|
||||||
**배열 비교 기록**에 backend, timing과 평가 요약이 남습니다.
|
실행하면 **비교 기록**에 배열, 알고리즘, 실제 backend, 위치추정/전체 timing과 평가 요약이 함께
|
||||||
|
남습니다.
|
||||||
- 입력을 바꾼 뒤 화면에 남은 결과는 이전 실행 snapshot이며 UI가 이전 설정 결과임을 표시합니다.
|
- 입력을 바꾼 뒤 화면에 남은 결과는 이전 실행 snapshot이며 UI가 이전 설정 결과임을 표시합니다.
|
||||||
- Camera에서 거리·음속·seed를 바꾼 Scene과 scan·STFT·band를 바꾼 Experiment는 우측의 각
|
- Camera에서 거리·음속·seed를 바꾼 Scene과 scan·STFT·band를 바꾼 Experiment는 우측의 각
|
||||||
**JSON 저장** 버튼으로 보존할 수 있습니다.
|
**JSON 저장** 버튼으로 보존할 수 있습니다.
|
||||||
- **전체 기록 JSON**은 세션에 남은 모든 배열 비교 요약을
|
- **전체 기록 JSON**은 세션에 남은 배열·알고리즘·backend 비교 요약을
|
||||||
`micarrsim.comparison-history` 문서로 저장합니다.
|
`micarrsim.comparison-history` 문서로 저장합니다.
|
||||||
|
|
||||||
미저장 Scene·Experiment·Result·비교 기록은 우측 저장 상태에 표시됩니다. 직전 Result를 저장하지
|
미저장 Scene·Experiment·Result·비교 기록은 우측 저장 상태에 표시됩니다. 직전 Result를 저장하지
|
||||||
@@ -131,7 +160,7 @@ curve는 합성 microphone channel에 항상 적용됩니다. **마이크 주파
|
|||||||
Scene source에 두 개 이상의 `trajectory` keyframe이 있으면 **Map 준비**가 활성화됩니다.
|
Scene source에 두 개 이상의 `trajectory` keyframe이 있으면 **Map 준비**가 활성화됩니다.
|
||||||
Builder에서는 **시간에 따라 음원 이동**과 경로 미리보기 slider로 이 데이터를 만들 수 있습니다.
|
Builder에서는 **시간에 따라 음원 이동**과 경로 미리보기 slider로 이 데이터를 만들 수 있습니다.
|
||||||
|
|
||||||
1. Map rate와 backend를 선택합니다. 처음에는 2 Hz와 Auto를 권장합니다.
|
1. 알고리즘, Map rate와 backend를 선택합니다. 처음에는 DAS, 2 Hz와 Auto를 권장합니다.
|
||||||
2. **Map 준비**를 누릅니다. 현재 입력 snapshot을 최대 48개, map당 최대 2,500 points의 짧은
|
2. **Map 준비**를 누릅니다. 현재 입력 snapshot을 최대 48개, map당 최대 2,500 points의 짧은
|
||||||
분석창으로 계산합니다.
|
분석창으로 계산합니다.
|
||||||
3. **재생** 또는 시간 slider로 이동합니다. Heatmap은 이웃한 acoustic map 사이를 보간하고
|
3. **재생** 또는 시간 slider로 이동합니다. Heatmap은 이웃한 acoustic map 사이를 보간하고
|
||||||
@@ -146,13 +175,15 @@ Scene 시간에 이어 붙입니다. 한 창 안에서는 중앙 시각의 위
|
|||||||
|
|
||||||
**Result JSON**은 검증을 통과한 `micarrsim.result` 문서만 저장합니다.
|
**Result JSON**은 검증을 통과한 `micarrsim.result` 문서만 저장합니다.
|
||||||
|
|
||||||
- `experimentId`, `arrayId`, `sceneId`, `createdAt`, 실제 `backend`
|
- `experimentId`, `arrayId`, `sceneId`, `createdAt`, 실제 `algorithm`과 `backend`
|
||||||
- 실행 입력 전체의 canonical SHA-256인 `inputHash`
|
- 실행 입력 전체의 canonical SHA-256인 `inputHash`
|
||||||
- `signalStats`: 정규화 전 peak, 적용 scale, clipped sample 수, 실제 음향 모델과 sparse
|
- `signalStats`: 정규화 전 peak, 적용 scale, clipped sample 수, 실제 음향 모델과 sparse
|
||||||
path 전체·종류별 수
|
path 전체·종류별 수
|
||||||
- `timingMs`: 전체, signal generation과 beamforming 시간
|
- `timingMs`: 전체, signal generation과 `localization`; 기존 소비자 호환용 `beamforming`은 같은
|
||||||
- band별 `rawMap` 선형 power, `displayMap`, 검출 `peaks`
|
위치추정 시간을 담는 alias
|
||||||
- 각 peak의 비보정 half-power 공분산과 RMS ellipse인 `beamSpread`
|
- band별 `rawMap`: DAS는 선형 `power`, PHAT 계열은 무차원 `score`; 화면용 `displayMap`과 검출
|
||||||
|
`peaks`
|
||||||
|
- 각 peak의 비보정 half-power/half-maximum 공분산과 RMS ellipse인 `beamSpread`
|
||||||
- 평가 설정과 `peakToSidelobeDb`, `energyInsideTruthRatio`, `precision`, `recall`,
|
- 평가 설정과 `peakToSidelobeDb`, `energyInsideTruthRatio`, `precision`, `recall`,
|
||||||
`mainLobeWidthM`
|
`mainLobeWidthM`
|
||||||
|
|
||||||
@@ -172,7 +203,8 @@ sensitivity/phase/frequency-response calibration은 적용하지만 결과는
|
|||||||
실제 동기식 microphone `Float32Array`를 Scene 합성 없이 위치추정하려면
|
실제 동기식 microphone `Float32Array`를 Scene 합성 없이 위치추정하려면
|
||||||
[실시간 위치추정 코어 포팅](../../docs/realtime-porting.md)의
|
[실시간 위치추정 코어 포팅](../../docs/realtime-porting.md)의
|
||||||
`createLocalizationPlan`, `localizeMultichannel` 또는
|
`createLocalizationPlan`, `localizeMultichannel` 또는
|
||||||
`StreamingDasLocalizer`를 사용하세요. 실시간성은 장치에서
|
`createStreamingLocalizer`를 사용하세요. portable config의 `algorithm`으로 같은 세 위치추정을
|
||||||
|
선택할 수 있습니다. 실시간성은 장치에서
|
||||||
`processingTimeMs <= deadlineMs`와 `deadlineMisses`·`droppedSamples`를
|
`processingTimeMs <= deadlineMs`와 `deadlineMisses`·`droppedSamples`를
|
||||||
측정해 판정해야 합니다.
|
측정해 판정해야 합니다.
|
||||||
|
|
||||||
|
|||||||
+110
-14
@@ -11,8 +11,9 @@ Snapshot 한 번의 처리 순서는 다음과 같다.
|
|||||||
1. tone, noise 또는 audio asset으로 음원 신호를 만든다.
|
1. tone, noise 또는 audio asset으로 음원 신호를 만든다.
|
||||||
2. 음원과 각 마이크 사이의 직접음 또는 희소 multipath 전달함수를 만든다.
|
2. 음원과 각 마이크 사이의 직접음 또는 희소 multipath 전달함수를 만든다.
|
||||||
3. 마이크별 `sensitivityDb`, `phaseOffsetDeg`와 `frequencyResponse`를 수신 신호에 적용한다.
|
3. 마이크별 `sensitivityDb`, `phaseOffsetDeg`와 `frequencyResponse`를 수신 신호에 적용한다.
|
||||||
4. 합성된 동기식 다채널 신호를 STFT하고 conventional DAS map을 계산한다.
|
4. 합성된 동기식 다채널 신호를 STFT하고 `beamforming.algorithm`으로 선택한 위치 추정
|
||||||
5. 설정에 따라 알려진 마이크 응답을 DAS에서 역보정하고 peak와 평가 지표를 구한다.
|
알고리즘의 scan map을 계산한다.
|
||||||
|
5. 알고리즘에 맞게 알려진 마이크 응답을 보정하고 map의 peak와 평가 지표를 구한다.
|
||||||
|
|
||||||
Scene의 `acoustics`를 생략하거나 `model: "free-field"`로 지정하면 기존 직접음 결과를
|
Scene의 `acoustics`를 생략하거나 `model: "free-field"`로 지정하면 기존 직접음 결과를
|
||||||
유지한다. `model: "shoebox"`는 직육면체 방 안에서 경로 수가 제한된 근사를 추가한다.
|
유지한다. `model: "shoebox"`는 직육면체 방 안에서 경로 수가 제한된 근사를 추가한다.
|
||||||
@@ -97,9 +98,91 @@ preset을 적용한다.
|
|||||||
각 source–microphone 직접 경로를 실제로 막을 때 하나씩 추가된다. 대략적인 합성 경로 예산은
|
각 source–microphone 직접 경로를 실제로 막을 때 하나씩 추가된다. 대략적인 합성 경로 예산은
|
||||||
`음원 수 × 마이크 수 × 수신점당 최대 경로`다. Camera는 실행 전에 이 예산을 표시한다.
|
`음원 수 × 마이크 수 × 수신점당 최대 경로`다. Camera는 실행 전에 이 예산을 표시한다.
|
||||||
|
|
||||||
반사·tail을 늘리면 beamforming의 `O(scan points × microphones × selected bins × STFT frames)`
|
반사·tail을 늘리면 신호 합성의 전달함수 누산도 늘어난다. DAS 계열의 scan 누산은 대략
|
||||||
뿐 아니라 신호 합성의 전달함수 누산도 늘어난다. 처음에는 50×50 grid와 자유음장으로 기준선을
|
`O(scan points × microphones × selected bins × STFT frames)`이고, GCC-PHAT는 pair별 상호
|
||||||
만들고, 같은 입력에서 preset을 하나씩 바꾸어 비교하는 것이 좋다.
|
상관을 만든 뒤 `O(scan points × (microphones - 1) × bands)` lookup을 수행한다. 어느 방식이든
|
||||||
|
STFT와 거리 cache 비용은 별도로 필요하다. 처음에는 50×50 grid와 자유음장으로 기준선을 만들고,
|
||||||
|
같은 입력에서 환경과 알고리즘을 하나씩 바꾸어 비교하는 것이 좋다.
|
||||||
|
|
||||||
|
## 위치 추정 알고리즘
|
||||||
|
|
||||||
|
마이크 `m`, STFT frame `t`, 주파수 `f`의 복소 spectrum을 `X_m(t, f)`, scan point `p`와
|
||||||
|
마이크 사이 거리를 `r_m(p)`, 파수를 `k = 2πf/c`라고 하자. `φ_m(f)`는 알려진 마이크의 정적
|
||||||
|
phase offset과, 주파수 응답 보정을 켠 경우 response phase를 합한 값이다. 모든 map은 scan point
|
||||||
|
마다 하나의 비음수 상대값을 만들지만, 그 값은 위치의 확률이나 posterior가 아니다.
|
||||||
|
|
||||||
|
### DAS (`das`)
|
||||||
|
|
||||||
|
Conventional frequency-domain delay-and-sum은 각 후보점에서 구면파 전파 위상을 되돌려 채널을
|
||||||
|
coherent sum한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
B_DAS(p,t,f) = (1/M) Σ_m A_m⁻¹(f) X_m(t,f) exp(j[k r_m(p) - φ_m(f)])
|
||||||
|
P_DAS(p) = mean_(t,f) |B_DAS(p,t,f)|²
|
||||||
|
```
|
||||||
|
|
||||||
|
`A_m⁻¹(f)`에는 sensitivity의 역 gain과, 설정한 경우 frequency-response gain의 제한된 역보정이
|
||||||
|
들어간다. 구현은 frame별 제곱 크기를 먼저 평균하고 선택 band의 bin들을 다시 평균한다. 따라서
|
||||||
|
Result의 `rawMap.scale`은 `power`지만, 절대 SPL로 calibration한 power가 아니라 같은 입력·설정
|
||||||
|
안에서 비교하는 선형 상대 power다. CPU와 WebGPU를 지원한다.
|
||||||
|
|
||||||
|
### DAS-PHAT (`das-phat`)
|
||||||
|
|
||||||
|
DAS-PHAT는 steering 전에 각 frame·bin·마이크 spectrum을 위상만 남기도록 정규화한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
U_m(t,f) = X_m(t,f) / |X_m(t,f)|
|
||||||
|
S_DAS-PHAT(p) = mean_(t,f) |(1/M) Σ_m U_m(t,f) exp(j[k r_m(p) - φ_m(f)])|²
|
||||||
|
```
|
||||||
|
|
||||||
|
한 frame·bin에서 최강 마이크 크기의 기본 `10⁻⁶`배인 상대 floor 이하의 값은 `0`으로 두어
|
||||||
|
무음이나 극소값의 불안정한 위상을 제외한다. 입력과 calibration의 amplitude gain은 coherent sum에 사용하지 않고,
|
||||||
|
알려진 phase만 보정한다. 그 결과 source spectrum이나 채널 gain 차이에 덜 끌릴 수 있지만 유용한
|
||||||
|
amplitude 정보도 버리며, 약한 bin의 위상과 multipath에 민감할 수 있다. `rawMap.scale`은 무차원
|
||||||
|
`score`이고 CPU와 WebGPU를 지원한다.
|
||||||
|
|
||||||
|
### GCC-PHAT (`gcc-phat`)
|
||||||
|
|
||||||
|
현재 GCC-PHAT는 배열 중심에서 가장 먼 마이크 하나를 결정적인 reference로 고르고, reference와
|
||||||
|
나머지 `M - 1`개 마이크의 pair만 사용한다. 각 band와 pair에 대해 다음 PHAT cross spectrum을
|
||||||
|
STFT frame에 걸쳐 평균한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
C_mr(t,f) = X_m(t,f) conj(X_r(t,f))
|
||||||
|
G_mr(f) = mean_t [C_mr(t,f) / max(|C_mr(t,f)|, floor)]
|
||||||
|
× exp(j[φ_r(f) - φ_m(f)])
|
||||||
|
```
|
||||||
|
|
||||||
|
기본 `floor`는 해당 band·pair의 모든 선택 bin과 frame에서 얻은 최대 cross-spectrum 크기의
|
||||||
|
`10⁻⁶`배다. 이 floor는 amplitude를 score 가중치로 쓰기 위한 것이 아니라 극소 cross spectrum의
|
||||||
|
불안정한 위상 정규화를 제한한다.
|
||||||
|
|
||||||
|
선택 band 밖의 bin은 `0`으로 두고 켤레 대칭 spectrum을 IFFT하여 원형 상호상관
|
||||||
|
`R_mr,b(ℓ)`을 만든다. scan point마다 far-field 각도 근사가 아니라 정확한 거리 차이로 near-field
|
||||||
|
예측 lag를 계산한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
ℓ_mr(p) = [r_m(p) - r_r(p)] sampleRate / c
|
||||||
|
Q_b(p) = Σ_(m≠r) R_mr,b(ℓ_mr(p))
|
||||||
|
K_b = I(0 ∈ b) + I(N/2 ∈ b) + 2 × #(나머지 positive bins)
|
||||||
|
S_b(p) = clamp[N Q_b(p) / ((M-1) K_b), 0, 1]
|
||||||
|
```
|
||||||
|
|
||||||
|
분수 sample lag는 IFFT 원형 상호상관의 이웃 두 sample을 선형 보간한다. Hermitian coefficient
|
||||||
|
수 `K_b`, IFFT의 `1/N`, reference pair 수로 나눈 뒤 음의 상관은 0으로 두어 score를 0–1로
|
||||||
|
제한한다. 따라서 같은 위치 가설의 raw GCC score는 scan 범위나 마이크 수 자체에 의해 재척도화되지
|
||||||
|
않는다. 이 값도 확률이나 calibration된 confidence는 아니다. `rawMap.scale`은 `score`다.
|
||||||
|
PHAT가 amplitude를 제거하므로 sensitivity와 frequency-response gain은 역보정하지 않고 알려진
|
||||||
|
phase만 보정한다. 현재 CPU만 지원하고 두 개 이상의 마이크가 필요하다.
|
||||||
|
|
||||||
|
GCC-PHAT는 broadband 신호에서 상호상관 peak가 뚜렷할수록 유리하다. 단일 tone이나 지나치게 좁은
|
||||||
|
band는 주기적으로 같은 phase를 만드는 lag가 많아 여러 위치가 비슷한 score를 얻을 수 있고,
|
||||||
|
반사음이나 여러 동시 음원은 pair 상관 peak를 섞는다. IFFT 길이가 `N = fftSize`이면 표현 가능한
|
||||||
|
비중첩 원형 lag는 절대값 `N/2` sample까지다. 현재 구현은 scan 전체의 최대 기하학적 lag가 이를
|
||||||
|
넘으면 실행을 거절하므로 FFT를 키우거나 array aperture 또는 scan 범위를 줄여야 한다. 이 검사는
|
||||||
|
원형 lag alias를 막지만 좁은 대역의 주기적 모호성, 제한된 bandwidth, scan grid 양자화까지
|
||||||
|
해결하지는 않는다. 단일 reference 방식은 모든 마이크 쌍을 쓰는 GCC보다 계산량이 작지만 pair
|
||||||
|
중복성과 고장 마이크에 대한 강건성도 작다.
|
||||||
|
|
||||||
## 마이크 주파수 응답
|
## 마이크 주파수 응답
|
||||||
|
|
||||||
@@ -126,11 +209,17 @@ preset을 적용한다.
|
|||||||
보간하고 측정 범위 밖에서는 가장 가까운 끝점 값을 유지한다. 합성기는 이 curve를 실제 마이크
|
보간하고 측정 범위 밖에서는 가장 가까운 끝점 값을 유지한다. 합성기는 이 curve를 실제 마이크
|
||||||
채널에 적용한다.
|
채널에 적용한다.
|
||||||
|
|
||||||
Experiment에서 `beamforming.compensateFrequencyResponse`를 생략하거나 `true`로 두면
|
합성기는 알고리즘과 무관하게 sensitivity, 정적 phase offset과 frequency-response curve를 수신
|
||||||
CPU와 WebGPU DAS가 선택 FFT bin에서 알려진 curve의 역 gain/phase를 적용한다. 응답 notch의
|
channel에 적용한다. 위치 추정에서의 역보정은 알고리즘별로 다르다.
|
||||||
무제한 역보정은 noise까지 크게 증폭할 수 있으므로 양의 보상 boost는
|
|
||||||
`beamforming.maxCompensationDb`로 제한하며 기본값은 24 dB다. 허용 범위는 0–120 dB이고
|
- DAS는 sensitivity 역 gain과 정적 phase를 항상 보정한다. `compensateFrequencyResponse`를
|
||||||
응답 peak를 줄이는 attenuation과 phase 보상은 이 boost 상한에 의해 잘리지 않는다.
|
생략하거나 `true`로 두면 response의 역 gain과 phase도 보정한다. 응답 notch의 무제한 gain
|
||||||
|
boost는 noise까지 키울 수 있으므로 `maxCompensationDb`로 제한하며 기본값은 24 dB, 허용 범위는
|
||||||
|
0–120 dB다. 응답 peak를 줄이는 attenuation과 phase 보상에는 이 boost 상한을 적용하지 않는다.
|
||||||
|
- DAS-PHAT와 GCC-PHAT는 amplitude를 정규화하므로 sensitivity와 response gain의 역보정을
|
||||||
|
사용하지 않는다. 정적 phase는 항상 보정하고, `compensateFrequencyResponse`가 `true`이면 알려진
|
||||||
|
response phase도 보정한다. 따라서 `maxCompensationDb`는 두 PHAT 알고리즘의 score에는 영향을
|
||||||
|
주지 않는다.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -147,8 +236,10 @@ CPU와 WebGPU DAS가 선택 FFT bin에서 알려진 curve의 역 gain/phase를
|
|||||||
```
|
```
|
||||||
|
|
||||||
Camera의 **마이크 주파수 응답 처리**에서 **측정 curve 적용 + 보정하지 않음**을 고르면 합성에는
|
Camera의 **마이크 주파수 응답 처리**에서 **측정 curve 적용 + 보정하지 않음**을 고르면 합성에는
|
||||||
curve가 남고 DAS 역보정만 꺼진다. 같은 배열에서 보정 유무의 robustness를 비교할 때 사용한다.
|
curve가 남고 위치 추정의 response gain/phase 역보정만 꺼진다. DAS-PHAT와 GCC-PHAT는 여전히
|
||||||
curve가 없는 마이크는 0 dB, 0°로 취급한다.
|
amplitude를 버리지만, curve가 신호 대 잡음과 relative floor 통과 여부에 준 영향까지 되돌리지는
|
||||||
|
못한다. 같은 배열에서 알려진 response 보정 유무의 robustness를 비교할 때 사용한다. curve가 없는
|
||||||
|
마이크는 0 dB, 0°로 취급한다.
|
||||||
|
|
||||||
## 결과에서 확인할 값
|
## 결과에서 확인할 값
|
||||||
|
|
||||||
@@ -162,6 +253,10 @@ Result `signalStats`에는 다음 선택 필드가 들어간다.
|
|||||||
같은 입력과 seed에서 환경 preset만 바꿨다면 이 값과 위치 오차·precision/recall·PSR을 함께
|
같은 입력과 seed에서 환경 preset만 바꿨다면 이 값과 위치 오차·precision/recall·PSR을 함께
|
||||||
비교할 수 있다.
|
비교할 수 있다.
|
||||||
|
|
||||||
|
Result 최상위 `algorithm`은 실제 실행한 `das`, `das-phat` 또는 `gcc-phat`를 기록한다. band의
|
||||||
|
`rawMap.scale`은 DAS에서 `power`, 두 PHAT 방식에서 `score`다. peak 정규화된 `displayMap`은
|
||||||
|
시각 비교용일 뿐 어느 scale도 확률분포나 신뢰구간으로 바꾸지 않는다.
|
||||||
|
|
||||||
## 정확도 범위와 제외 사항
|
## 정확도 범위와 제외 사항
|
||||||
|
|
||||||
이 구현은 FDTD/FEM/BEM이나 room impulse response 측정치를 대신하지 않는다. 다음 항목은
|
이 구현은 FDTD/FEM/BEM이나 room impulse response 측정치를 대신하지 않는다. 다음 항목은
|
||||||
@@ -175,8 +270,9 @@ Result `signalStats`에는 다음 선택 필드가 들어간다.
|
|||||||
- preamp, anti-alias filter, ADC quantization, channel clock jitter·drift
|
- preamp, anti-alias filter, ADC quantization, channel clock jitter·drift
|
||||||
- 실제 장착 구조와 마이크 위치 공차
|
- 실제 장착 구조와 마이크 위치 공차
|
||||||
|
|
||||||
따라서 preset의 RT60이나 wall gain은 특정 방을 인증하는 값이 아니라 배열과 DAS가 multipath에
|
따라서 preset의 RT60이나 wall gain은 특정 방을 인증하는 값이 아니라 배열과 위치 추정 알고리즘이
|
||||||
얼마나 민감한지 비교하는 조건이다. 실제 장치 성능을 평가할 때는 같은 Array/scan/band 설정으로
|
multipath에 얼마나 민감한지 비교하는 조건이다. 실제 장치 성능을 평가할 때는 같은
|
||||||
|
Array/scan/band 설정으로
|
||||||
동기식 실측 채널을 [실시간 위치추정 코어](realtime-porting.md)에 입력하고 합성 결과와 나란히
|
동기식 실측 채널을 [실시간 위치추정 코어](realtime-porting.md)에 입력하고 합성 결과와 나란히
|
||||||
비교해야 한다. 주파수 응답 curve만으로 noise floor, distortion, ADC와 clock 오차까지 모사되지는
|
비교해야 한다. 주파수 응답 curve만으로 noise floor, distortion, ADC와 clock 오차까지 모사되지는
|
||||||
않는다.
|
않는다.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# WebGPU 기준 실측
|
# WebGPU DAS 기준 실측
|
||||||
|
|
||||||
2026-08-28에 Chrome 151 headless, Intel Gen9 adapter에서 synthetic 1 kHz fixture를 측정했다. 입력은
|
2026-08-28에 Chrome 151 headless, Intel Gen9 adapter에서 synthetic 1 kHz fixture를 측정했다. 입력은
|
||||||
48 kHz · 0.25 s, 192 microphones, FFT 512 / hop 256, 900–1100 Hz band이며 16×16 warm-up 뒤 각
|
48 kHz · 0.25 s, 192 microphones, FFT 512 / hop 256, 900–1100 Hz band이며 16×16 warm-up 뒤 각
|
||||||
@@ -10,6 +10,19 @@
|
|||||||
| 100×100 | 176,640,000 | 251.4 ms | 2,102.0 ms | 36.91 MiB | 3.17× |
|
| 100×100 | 176,640,000 | 251.4 ms | 2,102.0 ms | 36.91 MiB | 3.17× |
|
||||||
| 200×200 | 706,560,000 | 891.9 ms | 4,206.7 ms | 80.47 MiB | 11.26× |
|
| 200×200 | 706,560,000 | 891.9 ms | 4,206.7 ms | 80.47 MiB | 11.26× |
|
||||||
|
|
||||||
|
이 표는 conventional DAS의 저장된 기준 측정이며 DAS-PHAT이나 GCC-PHAT의 실측값이 아니다.
|
||||||
|
50×50에서 CPU STFT median은 1,669.8 ms로 `end-to-end` 1,818.1 ms의 약 91.8%였고,
|
||||||
|
실제 GPU queue 구간은 79.2 ms였다. 별도로 한 번 수행한 192채널 signal 합성은 1,200.5 ms이며
|
||||||
|
위 `end-to-end` 열에 포함되지 않는다. 따라서 이 fixture에서는 scan MAC만 줄인 비율을 전체
|
||||||
|
Camera 실행 시간 향상으로 해석하면 안 된다.
|
||||||
|
|
||||||
|
같은 192채널·50×50·46 frames·2 bins·한 band를 식으로만 비교하면 DAS scan은
|
||||||
|
44,160,000 complex MAC이다. 현재 single-reference GCC-PHAT은 공통 forward STFT 뒤
|
||||||
|
35,144회의 2-pass cross-spectrum 연산, 191회의 inverse FFT와 477,500회의 point/pair
|
||||||
|
lookup을 수행한다. 이는 구현 연산량 비교이지 GCC 실측 benchmark가 아니며, 2 bins는 GCC-PHAT에
|
||||||
|
너무 좁어 주기적 지연 모호성이 크다. 정확도·시간 비교에는 band마다 8 bins 이상의 광대역 fixture와
|
||||||
|
같은 입력·장치·warm-up 조건을 사용해야 한다.
|
||||||
|
|
||||||
`GPU wall`은 host packing/`writeBuffer()` 호출 직후부터 queue에 들어간 transfer 완료, steering pass,
|
`GPU wall`은 host packing/`writeBuffer()` 호출 직후부터 queue에 들어간 transfer 완료, steering pass,
|
||||||
DAS pass와 readback까지 기다린 시간이다. `end-to-end`에는 이 host 작업과 장치/pipeline 초기화,
|
DAS pass와 readback까지 기다린 시간이다. `end-to-end`에는 이 host 작업과 장치/pipeline 초기화,
|
||||||
distance 생성, CPU STFT가 포함된다. 200×200은 64 MiB steering buffer 목표를 지키면서 두 FFT bin을
|
distance 생성, CPU STFT가 포함된다. 200×200은 64 MiB steering buffer 목표를 지키면서 두 FFT bin을
|
||||||
|
|||||||
+73
-19
@@ -8,7 +8,7 @@ micarrsim의 저장 형식은 JSON Schema Draft 2020-12와 추가 관계 검증
|
|||||||
|
|
||||||
- `micarrsim.array`: aperture와 마이크별 `[x, y, z]` 좌표
|
- `micarrsim.array`: aperture와 마이크별 `[x, y, z]` 좌표
|
||||||
- `micarrsim.scene`: 음원·ambient recipe, 위치 ground truth와 로컬 asset manifest
|
- `micarrsim.scene`: 음원·ambient recipe, 위치 ground truth와 로컬 asset manifest
|
||||||
- `micarrsim.experiment`: scan plane/grid, 주파수 대역, STFT와 DAS 설정
|
- `micarrsim.experiment`: scan plane/grid, 주파수 대역, STFT와 위치 추정 설정
|
||||||
- `micarrsim.result`: raw/display acoustic map, 복수 peak와 source 매칭, 평가·성능 정보
|
- `micarrsim.result`: raw/display acoustic map, 복수 peak와 source 매칭, 평가·성능 정보
|
||||||
- `micarrsim.comparison-history`: 세션의 배열별 Result 요약을 모은 편의 export. core schema
|
- `micarrsim.comparison-history`: 세션의 배열별 Result 요약을 모은 편의 export. core schema
|
||||||
검증 대상은 아니며 각 원본 Result JSON을 대신하지 않는다.
|
검증 대상은 아니며 각 원본 Result JSON을 대신하지 않는다.
|
||||||
@@ -18,17 +18,36 @@ scene JSON에는 192채널 원시 sample이나 원본 asset byte를 넣지 않
|
|||||||
`sha256` manifest로 참조한다. 사용자 컴퓨터의 절대 경로, URL, `..` 경로는 저장하지 않는다.
|
`sha256` manifest로 참조한다. 사용자 컴퓨터의 절대 경로, URL, `..` 경로는 저장하지 않는다.
|
||||||
|
|
||||||
array의 `sensitivityDb`와 `phaseOffsetDeg`는 각 마이크 수신 channel에 적용되는 편차다. 합성기는
|
array의 `sensitivityDb`와 `phaseOffsetDeg`는 각 마이크 수신 channel에 적용되는 편차다. 합성기는
|
||||||
이를 신호에 주입하고, beamformer는 알려진 calibration 값의 역 gain/phase를 적용한다. 선택적
|
이를 신호에 주입하고, 위치 추정기는 선택한 알고리즘의 규칙에 따라 알려진 calibration을 보정한다.
|
||||||
|
선택적
|
||||||
`frequencyResponse`는 2–64개의 `{ frequencyHz, gainDb, phaseDeg? }` 측정점이다.
|
`frequencyResponse`는 2–64개의 `{ frequencyHz, gainDb, phaseDeg? }` 측정점이다.
|
||||||
주파수는 0–1,000,000 Hz에서 중복 없이 증가해야 하며, dB와 wrapped phase를 구간 선형 보간하고
|
주파수는 0–1,000,000 Hz에서 중복 없이 증가해야 하며, dB와 wrapped phase를 구간 선형 보간하고
|
||||||
측정 범위 밖에서는 가까운 끝점을 사용한다.
|
측정 범위 밖에서는 가까운 끝점을 사용한다.
|
||||||
|
|
||||||
Experiment의 선택적 `beamforming.compensateFrequencyResponse`는 기본 `true`다. 합성
|
Experiment의 필수 `beamforming.algorithm` enum은 `das`, `das-phat`, `gcc-phat`다. backend와
|
||||||
channel에는 curve가 항상 적용되며, `true`이면 CPU/WebGPU DAS가 선택 bin에서 curve의
|
raw map 계약은 다음과 같다.
|
||||||
역 gain/phase도 적용한다. `false`이면 sensitivity/phase calibration은 유지하고 curve
|
|
||||||
역보정만 끈다. 선택적 `beamforming.maxCompensationDb`는 응답 notch의 역보정에서 양의
|
| algorithm | `rawMap.scale` | 허용 backend |
|
||||||
gain boost만 제한하는 0–120 dB 값이며 생략 시 24 dB다. 응답 peak를 줄이는 attenuation과
|
| --- | --- | --- |
|
||||||
phase 보상은 이 boost 상한을 그대로 적용하지 않는다.
|
| `das` | `power` | `cpu`, `webgpu`; `auto` 가능 |
|
||||||
|
| `das-phat` | `score` | `cpu`, `webgpu`; `auto` 가능 |
|
||||||
|
| `gcc-phat` | `score` | `cpu`; `auto`는 CPU 선택 |
|
||||||
|
|
||||||
|
`gcc-phat`에 명시적 `webgpu`를 조합하면 검증 오류이며, 마이크가 두 개 이상이어야 한다. 필드
|
||||||
|
그룹 이름 `beamforming`은 기존 계약과의 호환을 위해 유지하지만 세 알고리즘을 모두 선택하는 위치
|
||||||
|
추정 설정이다.
|
||||||
|
|
||||||
|
선택적 `beamforming.compensateFrequencyResponse`는 기본 `true`다. 합성 channel에는 curve가
|
||||||
|
항상 적용된다. DAS는 sensitivity와 정적 phase를 항상 역보정하고, 값이 `true`이면 선택 bin에서
|
||||||
|
curve의 gain과 phase도 역보정한다. DAS-PHAT와 GCC-PHAT는 입력과 calibration의 amplitude gain을
|
||||||
|
사용하지 않지만 정적 phase를 보정하며, 값이 `true`이면 알려진 curve phase도 보정한다. `false`는
|
||||||
|
모든 알고리즘에서 curve 보정만 끄고 정적 phase 보정은 유지한다.
|
||||||
|
|
||||||
|
선택적 `beamforming.maxCompensationDb`는 DAS가 응답 notch를 역보정할 때 양의 gain boost만
|
||||||
|
제한하는 0–120 dB 값이며 생략 시 24 dB다. 응답 peak를 줄이는 attenuation과 phase 보상은 이
|
||||||
|
boost 상한의 대상이 아니다. amplitude를 사용하지 않는 DAS-PHAT와 GCC-PHAT에는 이 값이 영향을
|
||||||
|
주지 않는다. 세 알고리즘의 계산식과 한계는
|
||||||
|
[음향 환경과 마이크 응답 모델](acoustic-model.md)에 설명한다.
|
||||||
|
|
||||||
## 로컬 asset 재연결
|
## 로컬 asset 재연결
|
||||||
|
|
||||||
@@ -80,24 +99,55 @@ room 안의 min/max, 고유 id, -120–0 dB의 `transmissionDb`와
|
|||||||
gain을 보존하고, `peak`는 합성 전 peak를 `targetPeak`에 맞춘다. result의 `signalStats`에는
|
gain을 보존하고, `peak`는 합성 전 peak를 `targetPeak`에 맞춘다. result의 `signalStats`에는
|
||||||
정규화 전 peak, 실제 scale, scale 적용 후에도 범위를 넘은 sample 수를 기록한다.
|
정규화 전 peak, 실제 scale, scale 적용 후에도 범위를 넘은 sample 수를 기록한다.
|
||||||
|
|
||||||
이는 acoustic map 표시 정규화와 별개다. result의 `rawMap`은 반드시 선형 power이고,
|
이는 acoustic map 표시 정규화와 별개다. result의 `rawMap.scale`은 알고리즘의 원래 비음수 map을
|
||||||
`displayMap`은 peak-normalized 값 또는 dB 값일 수 있다. 후처리 결과는 `processedMaps`에 넣어
|
뜻하는 `power` 또는 `score`다. DAS의 `power`는 절대 SPL로 calibration한 값이 아니며,
|
||||||
raw DAS map을 덮어쓰지 않는다.
|
DAS-PHAT와 GCC-PHAT의 `score`도 확률, likelihood 또는 confidence가 아니다. 합이 1이 되도록
|
||||||
|
정규화되지 않으며 서로 다른 scale이나 알고리즘의 절대값을 직접 비교해서는 안 된다.
|
||||||
|
GCC-PHAT raw score는 pair 수·band의 Hermitian coefficient 수·IFFT 크기로 나눈 0–1 양의
|
||||||
|
상관 응답이므로 scan 범위를 바꿔도 같은 위치 가설의 척도가 유지된다. 그래도 확률 calibration은
|
||||||
|
아니며 DAS-PHAT score와 절대값을 비교하는 용도가 아니다.
|
||||||
|
|
||||||
|
`displayMap`은 원래 scale, peak-normalized `normalized` 또는 `db`일 수 있다. peak 정규화는
|
||||||
|
최댓값을 1로 만드는 표시 변환일 뿐 확률 정규화가 아니다. `processedMaps`는 `damas`, `clean-sc`
|
||||||
|
또는 `custom` 후처리 결과를 별도로 교환하기 위한 예약 슬롯이다. 현재 위치 추정 코어는 DAMAS나
|
||||||
|
CLEAN-SC를 실행하거나 이 필드를 자동 생성하지 않으며, raw map을 후처리 map으로 덮어쓰지 않는다.
|
||||||
|
|
||||||
map은 row-major 배열이다. 첫 행은 `yMax`, 마지막 행은 `yMin`, 각 행은 `xMin`에서 `xMax`
|
map은 row-major 배열이다. 첫 행은 `yMax`, 마지막 행은 `yMin`, 각 행은 `xMin`에서 `xMax`
|
||||||
방향이다. `values.length`는 반드시 `rows × columns`와 같아야 한다.
|
방향이다. `values.length`는 반드시 `rows × columns`와 같아야 한다.
|
||||||
|
|
||||||
Experiment의 선택적 `evaluation.detectionThresholdRatio`는 최강 local peak power에 대한 검출
|
Experiment의 선택적 `evaluation.detectionThresholdRatio`는 최강 local peak의 같은-scale raw
|
||||||
임계 비율이며 `0 < ratio <= 1`이다. 생략된 이전 문서를 Camera에서 열면 기본값 `0.25`를 적용하며,
|
값에 대한 검출 임계 비율이며 `0 < ratio <= 1`이다. 생략된 이전 문서를 Camera에서 열면 기본값
|
||||||
Experiment JSON을 다시 저장하면 이 값이 명시된다. 값을 낮추면 약한 peak 후보를 포함하지만
|
`0.25`를 적용하며, Experiment JSON을 다시 저장하면 이 값이 명시된다. 값을 낮추면 약한 peak 후보를 포함하지만
|
||||||
sidelobe false positive도 늘 수 있다.
|
sidelobe false positive도 늘 수 있다.
|
||||||
|
|
||||||
## Result 평가 정보
|
## Result 평가 정보
|
||||||
|
|
||||||
각 band의 `peaks`는 위치와 power 값, 선택적 `sourceId`, `localizationErrorM`,
|
새 Result는 최상위 `algorithm`에 실제 실행한 `das`, `das-phat` 또는 `gcc-phat`를 기록하며
|
||||||
`localizationErrorPixels`, `beamSpread`를 저장한다. `beamSpread`는 선택 peak를 포함하는 연결된
|
Experiment의 선택값과 같아야 한다. 이 필드는 이전 `1.0.0` Result를 읽기 위해 schema상 선택적으로
|
||||||
half-power 성분의 power 가중 centroid·공분산과 major/minor RMS 반경·각도다. `calibrated`는 현재
|
남아 있지만 현재 export에는 항상 들어간다. `backend`는 요청값 `auto`가 아니라 실제 사용한
|
||||||
항상 `false`이며 확률분포, Gaussian 신뢰구간 또는 통계적 위치 불확실성으로 해석하지 않는다.
|
`cpu` 또는 `webgpu`다.
|
||||||
|
|
||||||
|
관계 검증은 `das → power`, `das-phat/gcc-phat → score`를 강제한다. Peak에 `beamSpread`가
|
||||||
|
있으면 power map은 power-weighted method, score map은 score-weighted method여야 한다. 따라서
|
||||||
|
구조상 유효하지만 의미가 모순된 외부 Result도 import 시 거절된다.
|
||||||
|
|
||||||
|
`timingMs.localization`은 선택한 위치 추정 알고리즘의 wall time이다. 현재 export는 기존 DAS 전용
|
||||||
|
소비자를 위해 같은 값을 `timingMs.beamforming`에도 호환 alias로 기록한다. `1.0.0` schema는 이전
|
||||||
|
문서를 위해 `beamforming`을 여전히 필수로 두므로, 새 writer는 `localization`과 `beamforming`을
|
||||||
|
함께 저장해야 한다. `timingMs.total`은 전체 시간이고 선택적 `signalGeneration`은 합성 시간이다.
|
||||||
|
|
||||||
|
각 band의 `peaks`는 위치와 해당 `rawMap.scale`의 값, 선택적 `sourceId`, `localizationErrorM`,
|
||||||
|
`localizationErrorPixels`, `beamSpread`를 저장한다. `beamSpread`는 선택 peak를 포함하는 8-connected
|
||||||
|
성분의 가중 centroid·공분산과 major/minor RMS 반경·각도다.
|
||||||
|
|
||||||
|
- `power` map은 `connected-half-power-power-weighted-covariance`를 사용해 peak의
|
||||||
|
`halfPowerRatio` 이상인 연결 성분을 power로 가중한다.
|
||||||
|
- `score` map은 `connected-half-maximum-score-weighted-covariance`를 사용해 peak의 같은 비율
|
||||||
|
이상인 연결 성분을 score로 가중한다. 호환 필드명 `halfPowerRatio`는 이 경우 실제로
|
||||||
|
half-maximum score 비율을 뜻한다.
|
||||||
|
|
||||||
|
두 방식 모두 `calibrated`는 현재 항상 `false`다. covariance ellipse는 map의 공간적 퍼짐을
|
||||||
|
결정적으로 요약할 뿐 확률분포, Gaussian 신뢰구간 또는 통계적 위치 불확실성이 아니다.
|
||||||
`metrics`에는 다음 유한값만 기록한다.
|
`metrics`에는 다음 유한값만 기록한다.
|
||||||
|
|
||||||
- `peakToSidelobeDb`
|
- `peakToSidelobeDb`
|
||||||
@@ -105,6 +155,9 @@ half-power 성분의 power 가중 centroid·공분산과 major/minor RMS 반경
|
|||||||
- `precision`, `recall`
|
- `precision`, `recall`
|
||||||
- `mainLobeWidthM`
|
- `mainLobeWidthM`
|
||||||
|
|
||||||
|
호환 필드명 `energyInsideTruthRatio`는 `power` map에서는 truth 주변 power 비율, `score` map에서는
|
||||||
|
truth 주변 score 비율이다. 후자의 값은 물리적 energy 비율이나 위치 확률이 아니다.
|
||||||
|
|
||||||
`evaluation`은 지표를 다시 해석할 수 있도록 truth 반경, source 매칭 tolerance, peak 검출
|
`evaluation`은 지표를 다시 해석할 수 있도록 truth 반경, source 매칭 tolerance, peak 검출
|
||||||
threshold와 최소 거리, sidelobe 제외 반경, half-power 비율, dynamic range, 최대 검출 수를
|
threshold와 최소 거리, sidelobe 제외 반경, half-power 비율, dynamic range, 최대 검출 수를
|
||||||
버전과 함께 저장한다. `environment`에는 실제 backend, microphone/grid 수, scan bounds와 z,
|
버전과 함께 저장한다. `environment`에는 실제 backend, microphone/grid 수, scan bounds와 z,
|
||||||
@@ -146,7 +199,8 @@ CPU 분석 계획은 기본 512 MiB, 반복 steering cache는 64 MiB, streaming
|
|||||||
256 MiB hard cap을 할당 전에 적용한다. 채널 순서와 streaming 상태 계약은
|
256 MiB hard cap을 할당 전에 적용한다. 채널 순서와 streaming 상태 계약은
|
||||||
[실측 다채널 위치추정 코어 포팅](realtime-porting.md)을 참고한다.
|
[실측 다채널 위치추정 코어 포팅](realtime-porting.md)을 참고한다.
|
||||||
|
|
||||||
portable block 결과의 `processingTimeMs`는 DAS와 local-peak 검출 wall time이다. Streaming
|
portable block 결과의 `processingTimeMs`는 선택한 위치 추정 알고리즘과 local-peak 검출 wall
|
||||||
|
time이다. Streaming
|
||||||
결과는 `deadlineMs`와 `deadlineMet`을 추가하고 상태에는 최근·최대 처리 시간,
|
결과는 `deadlineMs`와 `deadlineMet`을 추가하고 상태에는 최근·최대 처리 시간,
|
||||||
`deadlineMisses`와 `droppedSamples`를 누적한다. 이 runtime telemetry는
|
`deadlineMisses`와 `droppedSamples`를 누적한다. 이 runtime telemetry는
|
||||||
`micarrsim.result` 저장 스키마의 필수 필드가 아니다.
|
`micarrsim.result` 저장 스키마의 필수 필드가 아니다.
|
||||||
|
|||||||
+24
-18
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
> 구현 상태 · 2026-08-28
|
> 구현 상태 · 2026-08-28
|
||||||
>
|
>
|
||||||
> 단계 0–4와 단계 5의 저비용 음향 환경·마이크 응답·portable streaming core까지 완료했다.
|
> 단계 0–4와 단계 5의 저비용 음향 환경·마이크 응답·다중 알고리즘 portable streaming core까지 완료했다.
|
||||||
> 설치 없는 브라우저 앱, CPU/WebGPU DAS, Builder→Camera asset 재연결, 임의 오디오·이동
|
> 설치 없는 브라우저 앱, CPU/WebGPU DAS·DAS-PHAT와 CPU GCC-PHAT, Builder→Camera asset 재연결, 임의 오디오·이동
|
||||||
> trajectory, 빔 분포·복수 peak 감도, 라이브 시간축 재생, 배열 비교와 Result 내보내기를
|
> trajectory, 빔 분포·복수 peak 감도, 라이브 시간축 재생, 배열 비교와 Result 내보내기를
|
||||||
> 전체 자동 테스트로 검증했다. 실제 장치 adapter와 현장 검증은 장치 계약이 필요한 후속 범위다.
|
> 전체 자동 테스트로 검증했다. 실제 장치 adapter와 현장 검증은 장치 계약이 필요한 후속 범위다.
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
1. 기계음 데이터와 ambient audio를 조합해 장면 및 ground truth를 생성한다.
|
1. 기계음 데이터와 ambient audio를 조합해 장면 및 ground truth를 생성한다.
|
||||||
2. 배열 JSON과 장면 정보를 사용해 각 마이크에 도달하는 신호를 합성한다.
|
2. 배열 JSON과 장면 정보를 사용해 각 마이크에 도달하는 신호를 합성한다.
|
||||||
3. WGSL로 conventional delay-and-sum(DAS) 빔포밍을 수행한다.
|
3. DAS, DAS-PHAT 또는 GCC-PHAT로 위치 map을 계산하고 같은 입력에서 비교한다.
|
||||||
4. 주파수 구간별 acoustic image를 ground truth 위에 표시하고 정량 평가한다.
|
4. 주파수 구간별 acoustic image를 ground truth 위에 표시하고 정량 평가한다.
|
||||||
5. 배열, 거리, 음원, 주파수, grid 해상도를 바꾼 실험을 저장하고 비교한다.
|
5. 배열, 거리, 음원, 주파수, grid 해상도를 바꾼 실험을 저장하고 비교한다.
|
||||||
|
|
||||||
@@ -79,17 +79,21 @@ tap 수가 제한된 RT60 tail만 추가한다. 경로를 source–microphone
|
|||||||
|
|
||||||
DAS는 STFT 후 각 scan point와 마이크 사이 거리로 steering phase를 만들고, 선택된 주파수 bin의
|
DAS는 STFT 후 각 scan point와 마이크 사이 거리로 steering phase를 만들고, 선택된 주파수 bin의
|
||||||
정렬 합 power를 계산한다. 여러 주파수 구간은 각각 독립 map과 색을 갖는다. CPU reference를 먼저
|
정렬 합 power를 계산한다. 여러 주파수 구간은 각각 독립 map과 색을 갖는다. CPU reference를 먼저
|
||||||
작성한 뒤 같은 buffer layout으로 WGSL 결과를 대조한다. DAMAS, CLEAN-SC는 인터페이스만 마련하고
|
작성한 뒤 같은 buffer layout으로 WGSL 결과를 대조한다. DAS-PHAT은 각 frame/bin에서 마이크
|
||||||
초기 완료 범위에서는 제외한다.
|
spectrum의 진폭을 제거하되 알려진 응답 phase를 보정한다. GCC-PHAT은 한 reference와 나머지
|
||||||
|
마이크의 band-limited PHAT 상관을 IFFT하고 scan point의 near-field 예상 지연에서 보간한다.
|
||||||
|
DAMAS, CLEAN-SC는 초기 완료 범위에서 제외한다.
|
||||||
|
|
||||||
연산량의 주항은 대략 `O(P × M × F × T)`다. `M=192`, `P=50²=2,500`일 때 STFT
|
`P` points, `M` microphones, `T__ frames, `F` selected bins에서 DAS 계열 scan은
|
||||||
frame·주파수 bin 하나당
|
`O(P × M × T × F)`다. GCC-PHAT은 공통 forward STFT 외에 2-pass cross spectrum
|
||||||
약 48만 개의 복소 steering 누산이 필요하다. 100×100은 50×50보다 4배, 200×200은 16배이므로
|
`2(M-1)TΣF_b`, `(M-1)B` inverse FFT와 `P(M-1)B` lookup을 수행한다.
|
||||||
장치별 실제 GPU timing을 UI에 표시하고 목표 frame budget에 맞춰 해상도를 제한한다. 정확한 성능과
|
192채널·50×50·46 frames·2 bins의 DAS는 44,160,000 complex MAC이고 같은 한 band
|
||||||
메모리는 대표 GPU에서 benchmark하여 기록하며 이론치만으로 약속하지 않는다.
|
GCC scan은 477,500 lookup이다. 다만 작은 grid에서는 공통 STFT가 지배할 수 있으므로 이 비율을
|
||||||
|
end-to-end 속도 향상으로 해석하지 않는다. 100×100은 50×50보다 4배, 200×200은 16배 points이며
|
||||||
|
장치별 실제 timing과 메모리를 기록하고 이론치만으로 실시간성을 약속하지 않는다.
|
||||||
|
|
||||||
실측·반복 분석용 CPU 계획은 거리 행렬, bin calibration, 임시 map과 허용되는 steering matrix를
|
실측·반복 분석용 CPU 계획은 거리 행렬과 workspace를 재사용하고, DAS 계열은 bin calibration과
|
||||||
재사용한다. 192채널·50×50·2 bins를 10회 분석하는 기준에서 거리 계산은 4,800,000회에서
|
허용되는 steering matrix도 재사용한다. 192채널·50×50·2 bins를 10회 DAS 분석하는 기준에서 거리 계산은 4,800,000회에서
|
||||||
480,000회, steering pair는 9,600,000회에서 960,000회로 줄어든다. snapshot working set과 계획은
|
480,000회, steering pair는 9,600,000회에서 960,000회로 줄어든다. snapshot working set과 계획은
|
||||||
512 MiB, steering cache는 64 MiB, streaming input은 256 MiB 기본 hard cap을 할당 전에 적용한다.
|
512 MiB, steering cache는 64 MiB, streaming input은 256 MiB 기본 hard cap을 할당 전에 적용한다.
|
||||||
Streaming ring은 backlog에서 가장 오래된 sample을 버리고 호출당 결과 수를 제한한다.
|
Streaming ring은 backlog에서 가장 오래된 sample을 버리고 호출당 결과 수를 제한한다.
|
||||||
@@ -176,20 +180,21 @@ flattening이 모델 타당성을 훼손하는지 청취 및 spectrum 통계로
|
|||||||
- peak별 half-power 공분산/RMS 빔 분포와 재현 가능한 검출 임계값
|
- peak별 half-power 공분산/RMS 빔 분포와 재현 가능한 검출 임계값
|
||||||
- sample-aligned 준정적 시간창 분석, bounded map 계획과 이동 장면 재생
|
- sample-aligned 준정적 시간창 분석, bounded map 계획과 이동 장면 재생
|
||||||
|
|
||||||
완료 조건: 사용자가 코드 수정 없이 배열 JSON 두 개를 같은 장면에서 비교할 수 있다.
|
완료 조건: 사용자가 코드 수정 없이 배열 JSON과 위치 추정 알고리즘을 같은 장면에서 비교할 수 있다.
|
||||||
|
|
||||||
### 단계 5 — 현실성·포팅과 실제 데이터 · 부분 완료
|
### 단계 5 — 현실성·포팅과 실제 데이터 · 부분 완료
|
||||||
|
|
||||||
- [x] 마이크별 gain·phase·frequency-response 합성 및 선택적 DAS 역보정
|
- [x] 마이크별 gain·phase·frequency-response 합성과 알고리즘별 amplitude/phase 보정
|
||||||
- [x] 자유음장을 보존하는 선택형 shoebox 1차 반사·scattering·회절·RT60 tail
|
- [x] 자유음장을 보존하는 선택형 shoebox 1차 반사·scattering·회절·RT60 tail
|
||||||
- [x] Scene 합성에서 분리한 block/streaming multichannel 위치추정 API
|
- [x] Scene 합성에서 분리한 block/streaming multichannel 위치추정 API
|
||||||
- [x] 반복 거리·calibration·steering cache, bounded ring과 메모리 hard cap
|
- [x] 반복 거리·calibration·steering cache, bounded ring과 메모리 hard cap
|
||||||
|
- [x] DAS·DAS-PHAT·reference-pair GCC-PHAT와 알고리즘별 power/score 계약
|
||||||
- [ ] 라이선스 검토를 통과한 DCASE/MIMII adapter와 batch workflow
|
- [ ] 라이선스 검토를 통과한 DCASE/MIMII adapter와 batch workflow
|
||||||
- [ ] 실제 장치의 channel/clock/sample 형식에 맞춘 capture·transport adapter와 현장 검증
|
- [ ] 실제 장치의 channel/clock/sample 형식에 맞춘 capture·transport adapter와 현장 검증
|
||||||
- [ ] 필요 시 센서 self-noise·위치 공차와 DAMAS/CLEAN-SC 후처리
|
- [ ] 필요 시 센서 self-noise·위치 공차와 DAMAS/CLEAN-SC 후처리
|
||||||
|
|
||||||
현재 완료 조건은 기존 자유음장 결과를 유지한 채 propagation model과 응답 보상을 선택해
|
현재 완료 조건은 기존 자유음장 결과를 유지한 채 propagation model과 응답 보상을 선택해
|
||||||
재실행하고, 같은 CPU DAS를 실측 `Float32Array` channel에 직접 적용하는 것이다. 실제
|
재실행하고, 선택한 CPU 위치 추정기를 실측 `Float32Array` channel에 직접 적용하는 것이다. 실제
|
||||||
hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정한다.
|
hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정한다.
|
||||||
|
|
||||||
## 9. 주요 위험과 대응
|
## 9. 주요 위험과 대응
|
||||||
@@ -203,7 +208,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
|||||||
쓴다. 실제 데이터 adapter는 단계 5의 라이선스 검토 뒤 추가한다.
|
쓴다. 실제 데이터 adapter는 단계 5의 라이선스 검토 뒤 추가한다.
|
||||||
- 실제 AC와 simulation gap: gain·phase·주파수 응답과 희소 실내 환경을 비교 조건으로 제공하되,
|
- 실제 AC와 simulation gap: gain·phase·주파수 응답과 희소 실내 환경을 비교 조건으로 제공하되,
|
||||||
위치 공차·self-noise·ADC·clock은 실측 adapter와 현장 검증으로 다룬다.
|
위치 공차·self-noise·ADC·clock은 실측 adapter와 현장 검증으로 다룬다.
|
||||||
- post-processing이 기본 결과를 가림: raw DAS map과 후처리 map을 항상 별도로 보존한다.
|
- post-processing이 기본 결과를 가림: 알고리즘별 raw power/score map과 후처리 map을 별도로 보존한다.
|
||||||
|
|
||||||
## 10. 구현 결과와 다음 백로그
|
## 10. 구현 결과와 다음 백로그
|
||||||
|
|
||||||
@@ -211,6 +216,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
|||||||
- [x] array/scene/experiment/result schema와 synthetic fixture
|
- [x] array/scene/experiment/result schema와 synthetic fixture
|
||||||
- [x] 좌표·거리·구면 감쇠·분수 지연·STFT 단위 테스트
|
- [x] 좌표·거리·구면 감쇠·분수 지연·STFT 단위 테스트
|
||||||
- [x] CPU DAS golden implementation
|
- [x] CPU DAS golden implementation
|
||||||
|
- [x] CPU/WebGPU DAS-PHAT와 CPU reference-pair GCC-PHAT 구현·비교 UI
|
||||||
- [x] WGSL kernel, CPU/GPU 비교와 50²/100²/200² benchmark
|
- [x] WGSL kernel, CPU/GPU 비교와 50²/100²/200² benchmark
|
||||||
- [x] scene canvas, array view, parameter controls와 Result export
|
- [x] scene canvas, array view, parameter controls와 Result export
|
||||||
- [x] Builder→Camera SHA-256 asset 재연결 왕복 테스트
|
- [x] Builder→Camera SHA-256 asset 재연결 왕복 테스트
|
||||||
@@ -220,7 +226,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
|||||||
- [x] 복수 음원용 Experiment peak 검출 감도
|
- [x] 복수 음원용 Experiment peak 검출 감도
|
||||||
- [x] 마이크 주파수 응답 합성·CPU/WebGPU 역보정 비교
|
- [x] 마이크 주파수 응답 합성·CPU/WebGPU 역보정 비교
|
||||||
- [x] 자유음장·shoebox 희소 반사/산란/회절/RT60 환경 선택
|
- [x] 자유음장·shoebox 희소 반사/산란/회절/RT60 환경 선택
|
||||||
- [x] portable block/streaming localizer와 반복 DAS cache·메모리 상한
|
- [x] portable block/streaming localizer와 알고리즘별 반복 plan·메모리 상한
|
||||||
- [x] Camera 입력→설정→실행→확인의 Snapshot/Moving UI 재구성
|
- [x] Camera 입력→설정→실행→확인의 Snapshot/Moving UI 재구성
|
||||||
- [x] `test.cmd` one-command headless browser 검증
|
- [x] `test.cmd` one-command headless browser 검증
|
||||||
- [ ] DCASE/MIMII 라이선스 검토와 adapter
|
- [ ] DCASE/MIMII 라이선스 검토와 adapter
|
||||||
@@ -229,5 +235,5 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
|||||||
- [ ] DAMAS/CLEAN-SC 후처리
|
- [ ] DAMAS/CLEAN-SC 후처리
|
||||||
|
|
||||||
정확성 test를 먼저 통과시킨 뒤 UI 또는 최적화를 진행한다는 원칙은 유지한다. 추가 현실성 모델은
|
정확성 test를 먼저 통과시킨 뒤 UI 또는 최적화를 진행한다는 원칙은 유지한다. 추가 현실성 모델은
|
||||||
자유음장 DAS 결과를 바꾸지 않는 선택형 확장으로, 장치 연결은 portable localizer 앞의 adapter로
|
자유음장 DAS 기준 결과를 바꾸지 않는 선택형 확장으로, 장치 연결은 portable localizer 앞의 adapter로
|
||||||
추가한다.
|
추가한다.
|
||||||
|
|||||||
+59
-24
@@ -112,26 +112,48 @@
|
|||||||
<section class="guide-section">
|
<section class="guide-section">
|
||||||
<div class="section-number">04</div>
|
<div class="section-number">04</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Compute backend</p>
|
<p class="eyebrow">Localization & compute</p>
|
||||||
<h2>속도와 격자 선택</h2>
|
<h2>알고리즘, 속도와 격자 선택</h2>
|
||||||
|
<p class="guide-copy">
|
||||||
|
Camera의 <strong>위치 추정 알고리즘</strong>에서 실행할 방법을 고릅니다. 처음에는
|
||||||
|
DAS로 전체 흐름을 확인한 뒤 같은 scene·scan·STFT에서 PHAT 계열을 실행해 비교하세요.
|
||||||
|
</p>
|
||||||
|
<div class="guide-table-wrap">
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>알고리즘</th><th>raw map</th><th>Backend</th><th>특징</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>DAS</td><td>선형 power</td><td>CPU · WebGPU</td><td>진폭과 위상을 유지하는 기준선</td></tr>
|
||||||
|
<tr><td>DAS-PHAT</td><td>무차원 score</td><td>CPU · WebGPU</td><td>STFT 크기를 정규화한 위상 기반 합산</td></tr>
|
||||||
|
<tr><td>GCC-PHAT</td><td>무차원 score</td><td>CPU</td><td>기준 마이크 pair의 TDOA 상관</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div class="guide-table-wrap">
|
<div class="guide-table-wrap">
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>선택</th><th>동작</th><th>권장 상황</th></tr></thead>
|
<thead><tr><th>선택</th><th>동작</th><th>권장 상황</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>Auto (GPU→CPU)</td><td>WebGPU를 먼저 시도하고 불가능하면 CPU 사용</td><td>기본 권장</td></tr>
|
<tr><td>Auto (GPU→CPU)</td><td>WebGPU를 먼저 시도하고 불가능하면 CPU 사용</td><td>기본 권장</td></tr>
|
||||||
<tr><td>WebGPU 강제</td><td>GPU 장치가 없거나 실패하면 fallback 없이 오류</td><td>GPU 비교·측정</td></tr>
|
<tr><td>WebGPU 강제</td><td>DAS/DAS-PHAT를 GPU에서만 실행; 실패하면 fallback 없이 오류</td><td>GPU 비교·측정</td></tr>
|
||||||
<tr><td>CPU 강제</td><td>동일한 conventional DAS를 CPU에서 계산</td><td>호환성 확인·기준 비교</td></tr>
|
<tr><td>CPU 강제</td><td>선택한 알고리즘을 CPU에서 계산</td><td>호환성 확인·기준 비교</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
먼저 50×50을 권장합니다. 100×100은 4배, 200×200은 16배의 scan point를 계산합니다.
|
GCC-PHAT는 CPU 전용이므로 Auto가 자동으로 CPU를 사용하고 WebGPU 강제는 비활성화됩니다.
|
||||||
실행 중에는 취소할 수 있으며, 취소하거나 실패해도 이전 완료 결과는 유지됩니다.
|
각 band가 8개 미만의 FFT bin을 포함하면 협대역 상관 경고가 나오므로 band 폭이나 FFT
|
||||||
|
설정을 확인하세요.
|
||||||
</p>
|
</p>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
복수 음원에서 약한 peak가 빠지면 <strong>Peak 검출 임계값</strong>을 기본 25%에서
|
먼저 50×50을 권장합니다. 100×100은 4배, 200×200은 16배의 scan point를 계산합니다.
|
||||||
10–20%로 낮춰 보세요. 약한 후보와 함께 sidelobe 오검출도 늘 수 있으며, main lobe보다
|
연산량 줄은 공통 STFT transform과 함께 DAS/DAS-PHAT의 complex MAC, 또는 GCC-PHAT의
|
||||||
가까운 같은 대역 음원은 conventional DAS에서 하나로 합쳐질 수 있습니다.
|
two-pass cross-spectrum·pair×band inverse FFT·scan correlation lookup을 분리해
|
||||||
|
표시합니다. 이는 실행 시간 예측값이 아니며 장치와 입력에 따라 달라집니다. 실행 중에는
|
||||||
|
취소할 수 있고, 취소하거나 실패해도 이전 완료 결과는 유지됩니다.
|
||||||
|
</p>
|
||||||
|
<p class="guide-copy">
|
||||||
|
복수 음원에서 약한 peak가 빠지면 <strong>Peak 검출 임계값</strong>을 최강 map 값의
|
||||||
|
기본 25%에서 10–20%로 낮춰 보세요. 약한 후보와 함께 sidelobe 오검출도 늘 수 있으며,
|
||||||
|
main lobe보다 가까운 같은 대역 음원은 어느 알고리즘에서도 하나로 합쳐질 수 있습니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -144,11 +166,12 @@
|
|||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
고급 설정에서 자유음장 또는 흡음·일반·반사 강한 실내 preset을 고릅니다. 실내 모델은
|
고급 설정에서 자유음장 또는 흡음·일반·반사 강한 실내 preset을 고릅니다. 실내 모델은
|
||||||
1차 반사, scattering, occluder 회절과 제한된 RT60 tail을 희소 경로로 근사합니다.
|
1차 반사, scattering, occluder 회절과 제한된 RT60 tail을 희소 경로로 근사합니다.
|
||||||
Array의 마이크 응답 curve는 수신 신호에 적용하며 DAS 역보정 유무를 비교할 수 있습니다.
|
Array의 마이크 응답 curve는 수신 신호에 적용하며 위치추정 역보정 유무를 비교할 수 있습니다.
|
||||||
값과 한계는 <a href="/docs/acoustic-model.md">음향 모델 설명</a>에서 확인하세요.
|
값과 한계는 <a href="/docs/acoustic-model.md">음향 모델 설명</a>에서 확인하세요.
|
||||||
</p>
|
</p>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
실제 동기식 마이크 채널은 Scene 합성 없이 portable CPU DAS에 넣을 수 있습니다.
|
실제 동기식 마이크 채널은 Scene 합성 없이 portable CPU 위치추정 코어에 넣고
|
||||||
|
DAS·DAS-PHAT·GCC-PHAT를 선택할 수 있습니다.
|
||||||
장치별 channel·clock·transport adapter는 별도로 필요하며 실시간 deadline은 해당
|
장치별 channel·clock·transport adapter는 별도로 필요하며 실시간 deadline은 해당
|
||||||
장치에서 <code>processingTimeMs ≤ deadlineMs</code>와 miss·drop 누계로 확인해야
|
장치에서 <code>processingTimeMs ≤ deadlineMs</code>와 miss·drop 누계로 확인해야
|
||||||
합니다. <a href="/docs/realtime-porting.md">포팅 설명서</a>에 입력 형식, ring buffer,
|
합니다. <a href="/docs/realtime-porting.md">포팅 설명서</a>에 입력 형식, ring buffer,
|
||||||
@@ -163,19 +186,26 @@
|
|||||||
<p class="eyebrow">Result JSON</p>
|
<p class="eyebrow">Result JSON</p>
|
||||||
<h2>무엇이 저장되나요?</h2>
|
<h2>무엇이 저장되나요?</h2>
|
||||||
<dl class="result-list">
|
<dl class="result-list">
|
||||||
<div><dt>rawMap / displayMap</dt><dd>선형 power 원본과 화면 표시용 acoustic map</dd></div>
|
<div><dt>algorithm / backend</dt><dd>실제로 실행한 위치추정과 CPU·WebGPU 경로</dd></div>
|
||||||
|
<div><dt>rawMap / displayMap</dt><dd>DAS 선형 power 또는 PHAT 무차원 score와 화면 표시용 map</dd></div>
|
||||||
<div><dt>peaks</dt><dd>검출 위치, source 매칭, m·pixel 위치 오차</dd></div>
|
<div><dt>peaks</dt><dd>검출 위치, source 매칭, m·pixel 위치 오차</dd></div>
|
||||||
<div><dt>beamSpread</dt><dd>half-power lobe의 power 가중 공분산과 1× RMS ellipse</dd></div>
|
<div><dt>beamSpread</dt><dd>half-power 또는 half-maximum 응답의 map 값 가중 공분산과 1× RMS ellipse</dd></div>
|
||||||
<div><dt>metrics</dt><dd>energy 비율, precision/recall, sidelobe, main-lobe 폭</dd></div>
|
<div><dt>metrics</dt><dd>truth concentration, precision/recall, sidelobe, main-lobe 폭</dd></div>
|
||||||
<div><dt>evaluation</dt><dd>검출 threshold, 반경, tolerance 등 지표 계산 조건</dd></div>
|
<div><dt>evaluation</dt><dd>검출 threshold, 반경, tolerance 등 지표 계산 조건</dd></div>
|
||||||
<div><dt>signalStats</dt><dd>normalization·clipping과 실제 음향 모델·종류별 sparse path 수</dd></div>
|
<div><dt>signalStats</dt><dd>normalization·clipping과 실제 음향 모델·종류별 sparse path 수</dd></div>
|
||||||
<div><dt>timing / environment</dt><dd>backend, grid·scan 범위, 장치 정보와 구간별 시간</dd></div>
|
<div><dt>timing / environment</dt><dd>signal generation·localization 시간, backend, grid·scan과 장치 정보</dd></div>
|
||||||
<div><dt>inputHash</dt><dd>Array·Scene·Experiment 입력을 묶은 SHA-256 재현성 식별자</dd></div>
|
<div><dt>inputHash</dt><dd>Array·Scene·Experiment 입력을 묶은 SHA-256 재현성 식별자</dd></div>
|
||||||
<div><dt>comparison-history</dt><dd>세션의 배열별 시간·위치 오차·PSR 요약을 한 번에 저장</dd></div>
|
<div><dt>comparison-history</dt><dd>배열·알고리즘·실제 backend별 시간·위치 오차·PSR 요약</dd></div>
|
||||||
</dl>
|
</dl>
|
||||||
<aside class="callout">
|
<aside class="callout">
|
||||||
화면의 <strong>빔 분포</strong> 1×/2× RMS contour는 acoustic power lobe의 모양입니다.
|
DAS map은 acoustic power 응답이고 PHAT map은 무차원 위치추정 score입니다. score와
|
||||||
위치 확률, Gaussian 신뢰구간 또는 보정된 측정 불확실성이 아닙니다.
|
화면의 <strong>빔 분포</strong> 1×/2× RMS contour는 위치 확률, Gaussian 신뢰구간 또는
|
||||||
|
보정된 측정 불확실성이 아닙니다. GCC-PHAT의 0–1 raw score도 pair·band·IFFT scale을
|
||||||
|
제거한 양의 상관 응답이지 “확률 80%” 같은 의미가 아닙니다.
|
||||||
|
</aside>
|
||||||
|
<aside class="callout">
|
||||||
|
<code>timingMs.localization</code>은 위치추정 시간을 기록합니다. 기존 Result 소비자와의
|
||||||
|
호환을 위해 <code>timingMs.beamforming</code>에도 같은 값이 alias로 남습니다.
|
||||||
</aside>
|
</aside>
|
||||||
<aside class="callout">
|
<aside class="callout">
|
||||||
평가는 tone 음원을 해당 주파수 대역이 tone 주파수를 포함할 때만 정답으로 사용합니다.
|
평가는 tone 음원을 해당 주파수 대역이 tone 주파수를 포함할 때만 정답으로 사용합니다.
|
||||||
@@ -183,7 +213,7 @@
|
|||||||
에너지를 자동 판정하는 기능은 아직 없습니다.
|
에너지를 자동 판정하는 기능은 아직 없습니다.
|
||||||
</aside>
|
</aside>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
Camera에서 바꾼 Scene과 Experiment는 각각 저장할 수 있습니다. 완료 Result와 배열 비교
|
Camera에서 바꾼 Scene과 Experiment는 각각 저장할 수 있습니다. 완료 Result와 비교
|
||||||
기록도 별도 JSON으로 저장하세요. 저장하지 않은 항목이나 실행 중인 계산이 있으면
|
기록도 별도 JSON으로 저장하세요. 저장하지 않은 항목이나 실행 중인 계산이 있으면
|
||||||
페이지를 닫을 때 브라우저가 확인합니다.
|
페이지를 닫을 때 브라우저가 확인합니다.
|
||||||
</p>
|
</p>
|
||||||
@@ -213,7 +243,11 @@
|
|||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>WebGPU가 없거나 실행이 너무 느립니다.</summary>
|
<summary>WebGPU가 없거나 실행이 너무 느립니다.</summary>
|
||||||
<p>Backend를 Auto 또는 CPU로 두고 50×50 grid부터 실행하세요. 최신 Chrome/Edge와 그래픽 드라이버도 확인하세요.</p>
|
<p>Backend를 Auto 또는 CPU로 두고 50×50 grid부터 실행하세요. GCC-PHAT는 원래 CPU 전용입니다. DAS/DAS-PHAT WebGPU를 쓴다면 최신 Chrome/Edge와 그래픽 드라이버도 확인하세요.</p>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>GCC-PHAT에 8 bins 경고가 나옵니다.</summary>
|
||||||
|
<p>각 band가 포함하는 FFT bin이 너무 적으면 PHAT 상관이 협대역 주기성에 민감해집니다. 필요한 신호 대역 안에서 band를 넓히거나 FFT size를 조정하세요.</p>
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>두 번째 음원을 찾지 못합니다.</summary>
|
<summary>두 번째 음원을 찾지 못합니다.</summary>
|
||||||
@@ -233,10 +267,11 @@
|
|||||||
<h2>현재 모델의 범위</h2>
|
<h2>현재 모델의 범위</h2>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
micarrsim 1.0은 점 음원의 자유음장과 계산량을 제한한 shoebox 희소 경로, 마이크
|
micarrsim 1.0은 점 음원의 자유음장과 계산량을 제한한 shoebox 희소 경로, 마이크
|
||||||
주파수 응답과 conventional DAS를 제공합니다. 파동 방정식·고차 반사·재질별 흡음,
|
주파수 응답과 DAS·DAS-PHAT·GCC-PHAT를 제공합니다. 파동 방정식·고차 반사·재질별
|
||||||
복잡한 mesh, sensor self-noise·비선형, ADC·clock, DAMAS/CLEAN-SC와 자동 장치
|
흡음, 복잡한 mesh, sensor self-noise·비선형, ADC·clock, DAMAS/CLEAN-SC 후처리와
|
||||||
capture adapter는 포함하지 않습니다. 결과는 장비의 절대 성능 보증이 아니라 같은
|
자동 장치 capture adapter는 포함하지 않습니다. 실행할 수 없는 DAMAS/CLEAN-SC
|
||||||
조건에서 배열과 알고리즘을 비교하는 재현 가능한 기준입니다.
|
placeholder는 Camera UI에서 제거했습니다. 결과는 장비의 절대 성능 보증이 아니라
|
||||||
|
같은 조건에서 배열과 알고리즘을 비교하는 재현 가능한 기준입니다.
|
||||||
</p>
|
</p>
|
||||||
<p class="guide-copy">
|
<p class="guide-copy">
|
||||||
원본 asset은 브라우저 메모리에서만 읽고 서버나 외부 네트워크로 보내지 않습니다.
|
원본 asset은 브라우저 메모리에서만 읽고 서버나 외부 네트워크로 보내지 않습니다.
|
||||||
|
|||||||
+175
-35
@@ -1,7 +1,7 @@
|
|||||||
# 실측 다채널 위치추정 코어 포팅
|
# 실측 다채널 위치추정 코어 포팅
|
||||||
|
|
||||||
`packages/acoustics-core/realtime-localizer.js`는 Scene 생성이나 음향 합성 없이 이미 sampling된
|
`packages/acoustics-core/realtime-localizer.js`는 Scene 생성이나 음향 합성 없이 이미 sampling된
|
||||||
동기식 마이크 채널을 conventional CPU DAS에 직접 넣는다. 브라우저 DOM과 외부 package에
|
동기식 마이크 채널을 CPU DAS·DAS-PHAT·GCC-PHAT 위치 추정에 직접 넣는다. 브라우저 DOM과 외부 package에
|
||||||
의존하지 않는 ES module이므로, 실제 장치 adapter 뒤에 붙이거나 다른 프로젝트로 분리할 수 있다.
|
의존하지 않는 ES module이므로, 실제 장치 adapter 뒤에 붙이거나 다른 프로젝트로 분리할 수 있다.
|
||||||
|
|
||||||
이 API는 ADC와 transport를 제어하지 않는다. 입력 channel을 획득·정렬·동기화한 다음 위치 map과
|
이 API는 ADC와 transport를 제어하지 않는다. 입력 channel을 획득·정렬·동기화한 다음 위치 map과
|
||||||
@@ -9,13 +9,16 @@
|
|||||||
|
|
||||||
## 최소 복사 단위
|
## 최소 복사 단위
|
||||||
|
|
||||||
직접 경로로 `realtime-localizer.js`를 import한다면 다음 여덟 파일과 상대 경로를 함께
|
직접 경로로 `realtime-localizer.js`를 import한다면 다음 열한 파일과 상대 경로를 함께
|
||||||
복사하면 된다.
|
복사하면 된다.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
acoustics-core/
|
acoustics-core/
|
||||||
realtime-localizer.js
|
realtime-localizer.js
|
||||||
|
localization.js
|
||||||
|
localization-algorithms.js
|
||||||
das.js
|
das.js
|
||||||
|
gcc-phat.js
|
||||||
stft.js
|
stft.js
|
||||||
fft.js
|
fft.js
|
||||||
math.js
|
math.js
|
||||||
@@ -24,8 +27,10 @@ acoustics-core/
|
|||||||
evaluation.js
|
evaluation.js
|
||||||
```
|
```
|
||||||
|
|
||||||
`index.js`는 전체 core의 편의 export이므로 최소 포팅에는 필요하지 않다. 현재 portable API는
|
`index.js`는 전체 core의 편의 export이므로 최소 포팅에는 필요하지 않다. Portable API와
|
||||||
CPU 기준 구현이며 Camera의 WebGPU worker나 Scene·propagation 모듈을 요구하지 않는다.
|
`localization.js`의 analysis plan은 CPU 기준 구현이며 Camera의 WebGPU worker나 Scene·propagation
|
||||||
|
모듈을 요구하지 않는다. Camera backend 통합은 DAS와 DAS-PHAT에 WebGPU를 제공하지만 GCC-PHAT는
|
||||||
|
CPU only다. GCC-PHAT에 명시적 WebGPU를 요청하면 오류가 나며 `auto`는 CPU를 선택한다.
|
||||||
|
|
||||||
## 입력 계약
|
## 입력 계약
|
||||||
|
|
||||||
@@ -68,6 +73,58 @@ const array = {
|
|||||||
`beamforming.maxCompensationDb`로 제한하며 기본 24 dB, 허용 범위 0–120 dB다.
|
`beamforming.maxCompensationDb`로 제한하며 기본 24 dB, 허용 범위 0–120 dB다.
|
||||||
응답 peak를 줄이는 attenuation과 phase 보상은 이 boost 상한에 의해 잘리지 않는다.
|
응답 peak를 줄이는 attenuation과 phase 보상은 이 boost 상한에 의해 잘리지 않는다.
|
||||||
|
|
||||||
|
## 알고리즘 선택과 결과 scale
|
||||||
|
|
||||||
|
Portable plan은 top-level `algorithm`으로 위치 추정기를 선택한다. 이 값을 생략하면 기존 동작과
|
||||||
|
결과를 유지하는 `das`다. 기존 구성 형태인 `beamforming.algorithm`도 허용한다.
|
||||||
|
|
||||||
|
| `algorithm` | 핵심 계산 | `rawScale` | portable backend |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `das` | frequency-domain delay-and-sum | `power` | CPU |
|
||||||
|
| `das-phat` | phase-only spectrum을 steering하는 DAS | `score` | CPU |
|
||||||
|
| `gcc-phat` | 한 reference mic에 대한 `M-1`개 GCC-PHAT 지연 scan | `score` | CPU only |
|
||||||
|
|
||||||
|
같은 array·scan·band·STFT로 알고리즘을 비교할 때도 알고리즘마다 별도 plan을 만든다.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const dasPlan = createLocalizationPlan({
|
||||||
|
...commonConfig,
|
||||||
|
algorithm: "das",
|
||||||
|
});
|
||||||
|
|
||||||
|
const dasPhatPlan = createLocalizationPlan({
|
||||||
|
...commonConfig,
|
||||||
|
algorithm: "das-phat",
|
||||||
|
phatRelativeFloor: 1e-6,
|
||||||
|
});
|
||||||
|
|
||||||
|
const gccPhatPlan = createLocalizationPlan({
|
||||||
|
...commonConfig,
|
||||||
|
algorithm: "gcc-phat",
|
||||||
|
phatFloorRatio: 1e-6,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
`phatRelativeFloor`는 DAS-PHAT의 channel spectrum 정규화 floor이고, `phatFloorRatio`는
|
||||||
|
GCC-PHAT pair cross spectrum 정규화 floor다. 둘 다 해당 묶음의 최대 magnitude에 대한 0~1
|
||||||
|
비율이며 기본값은 `1e-6`이다. GCC-PHAT는 `phatRelativeFloor`도 호환 alias로 받지만 새 코드에서는
|
||||||
|
`phatFloorRatio`를 쓰는 편이 의미가 명확하다. 값을 키우면 낮은 magnitude 성분의 기여가 줄어들지만
|
||||||
|
너무 크게 두면 유효한 broadband 정보도 약해질 수 있으므로 현장 데이터로 조정한다.
|
||||||
|
|
||||||
|
각 band는 `rawScale`을 반환한다. `rawValue`는 scale에 관계없이 읽을 수 있는 canonical peak
|
||||||
|
값이다. `rawPower`는 `rawScale === "power"`, `rawScore`는 `rawScale === "score"`인 peak에만
|
||||||
|
사용하는 편의 alias이며 두 필드가 항상 함께 있다고 가정하면 안 된다. `score`는 음향 power,
|
||||||
|
확률 또는 신뢰도가 아니라 동일 알고리즘·설정 안에서 상대 peak를 비교하는 비보정 값이다.
|
||||||
|
`power`도 capture amplitude와 calibration이 절대 단위로 교정되지 않았다면 W 또는 Pa²가 아니다.
|
||||||
|
GCC-PHAT의 raw score는 pair 수·band coefficient 수·IFFT 크기로 정규화한 0–1 양의 상관 응답이라
|
||||||
|
scan 범위와 microphone 수 자체에 따른 척도 변화는 피하지만, 확률로 보정된 confidence는 아니다.
|
||||||
|
|
||||||
|
GCC-PHAT에는 여러 FFT bin에 에너지가 있는 broadband 입력을 권장한다. Band당 8 bin 미만도 hard
|
||||||
|
error는 아니지만 단일 tone이나 좁은 band에서는 반복 correlation peak 때문에 위치가 모호할 수 있다.
|
||||||
|
Plan 생성 시 reference pair와 scan point에서 가능한 최대 절대 기하 지연을 계산하며, 이 값이
|
||||||
|
`fftSize / 2` sample을 넘으면 circular alias를 막기 위해 거절한다. 더 큰 `fftSize`를 쓰거나
|
||||||
|
배열·scan 기하를 줄여야 하며, 결과의 `maximumLagSamples`로 실제 상한을 기록할 수 있다.
|
||||||
|
|
||||||
## 공통 계획 만들기
|
## 공통 계획 만들기
|
||||||
|
|
||||||
Array, scan grid, band와 STFT 설정이 바뀌지 않는 동안 계획을 한 번 만들고 재사용한다.
|
Array, scan grid, band와 STFT 설정이 바뀌지 않는 동안 계획을 한 번 만들고 재사용한다.
|
||||||
@@ -94,6 +151,7 @@ const plan = createLocalizationPlan({
|
|||||||
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
||||||
],
|
],
|
||||||
stft: { fftSize: 512, hopSize: 256 },
|
stft: { fftSize: 512, hopSize: 256 },
|
||||||
|
algorithm: "das", // "das" | "das-phat" | "gcc-phat"
|
||||||
speedOfSound: 343,
|
speedOfSound: 343,
|
||||||
normalization: "peak",
|
normalization: "peak",
|
||||||
compensateFrequencyResponse: true,
|
compensateFrequencyResponse: true,
|
||||||
@@ -113,19 +171,63 @@ const plan = createLocalizationPlan({
|
|||||||
- scan의 `columns`와 `rows`는 양의 정수
|
- scan의 `columns`와 `rows`는 양의 정수
|
||||||
- `speedOfSound`는 양수
|
- `speedOfSound`는 양수
|
||||||
- `normalization`은 `peak` 또는 `none`
|
- `normalization`은 `peak` 또는 `none`
|
||||||
|
- `algorithm`은 `das`, `das-phat`, `gcc-phat` 중 하나
|
||||||
|
- `phatRelativeFloor`와 `phatFloorRatio`는 지정한 경우 0–1
|
||||||
- `maxCompensationDb`는 0–120 dB
|
- `maxCompensationDb`는 0–120 dB
|
||||||
- `peakDetection.thresholdRatio`는 0–1,
|
- `peakDetection.thresholdRatio`는 0–1,
|
||||||
`minimumPeakDistanceM`는 0 이상,
|
`minimumPeakDistanceM`는 0 이상,
|
||||||
`maximumDetections`는 1–128의 정수
|
`maximumDetections`는 1–128의 정수
|
||||||
|
|
||||||
계획은 거리 행렬, bin calibration, 임시 map과 허용되는 경우 steering matrix를 유지하는
|
계획은 알고리즘별 거리 행렬과 workspace를 유지하는 stateful 객체다. DAS 계열은 bin calibration,
|
||||||
stateful 객체다. 같은 계획으로 두 분석을 동시에 실행하지 말고, worker마다 별도 계획을 만든다.
|
임시 map과 허용되는 경우 steering matrix를 유지하고, GCC-PHAT는 reference mic 선택,
|
||||||
Array·scan·band·STFT를 바꾸면 새 계획을 만들어야 한다.
|
STFT·correlation workspace를 유지한다. 같은 계획으로 두 분석을 동시에 실행하지 말고 worker마다
|
||||||
|
별도 계획을 만든다. Array·scan·band·STFT·알고리즘을 바꾸면 새 계획을 만들어야 한다.
|
||||||
|
Portable plan의 generic cache는 `plan.analysisPlan`이며 기존 호출자를 위해 DAS 계열에는
|
||||||
|
`plan.dasPlan`, GCC-PHAT에는 `plan.gccPhatPlan` alias도 제공한다.
|
||||||
|
|
||||||
portable 계획의 기본 compute batch는 scan point 256개와 STFT transform 128개 단위로 event
|
portable 계획의 기본 scan point batch는 DAS 계열 256개, GCC-PHAT 4,096개이고 STFT transform
|
||||||
loop에 양보한다. `computeOptions.pointBatchSize`와
|
batch는 128개다. GCC-PHAT cross-spectrum은 16,384 operation 단위로도 양보한다. 각 batch 경계에서
|
||||||
`computeOptions.stftTransformBatchSize`로 조정할 수 있지만, 큰 batch는 throughput과
|
event loop에 기회를 주며 `computeOptions.pointBatchSize`,
|
||||||
취소·UI 응답성의 trade-off가 있으므로 장치에서 함께 측정한다.
|
`computeOptions.stftTransformBatchSize`, `computeOptions.crossSpectrumBatchSize`로 조정할
|
||||||
|
수 있다. 큰 batch는 throughput과 취소·UI 응답성의 trade-off가 있으므로 장치에서 함께 측정한다.
|
||||||
|
|
||||||
|
낮은 수준에서 직접 사용할 때는 `localization.js`의 generic plan과 compute 함수를 짝지어 쓴다.
|
||||||
|
Plan compatibility는 값이 같은 새 객체가 아니라 생성할 때 넘긴 `arrayDefinition`, `scene`,
|
||||||
|
`experiment`의 정확히 같은 객체를 요구한다.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
computeLocalizationMap,
|
||||||
|
createLocalizationAnalysisPlan,
|
||||||
|
} from "./acoustics-core/localization.js";
|
||||||
|
|
||||||
|
const experiment = {
|
||||||
|
stft: { fftSize: 512, hopSize: 256, window: "hann" },
|
||||||
|
scan,
|
||||||
|
frequencyBands: bands,
|
||||||
|
beamforming: { algorithm: "das-phat", normalization: "peak" },
|
||||||
|
};
|
||||||
|
const scene = { speedOfSound: 343 };
|
||||||
|
const analysisPlan = createLocalizationAnalysisPlan({
|
||||||
|
sampleRate: 48_000,
|
||||||
|
arrayDefinition: array,
|
||||||
|
scene,
|
||||||
|
experiment,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const channels of capturedBlocks) {
|
||||||
|
const result = await computeLocalizationMap({
|
||||||
|
channels,
|
||||||
|
sampleRate: 48_000,
|
||||||
|
arrayDefinition: array,
|
||||||
|
scene,
|
||||||
|
experiment,
|
||||||
|
analysisPlan,
|
||||||
|
phatRelativeFloor: 1e-6,
|
||||||
|
});
|
||||||
|
consume(result);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 한 블록 분석
|
## 한 블록 분석
|
||||||
|
|
||||||
@@ -144,22 +246,28 @@ const result = await localizeMultichannel({
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const location of result.locations) {
|
for (const location of result.locations) {
|
||||||
console.log(location.bandId, location.position, location.rawPower);
|
console.log(
|
||||||
|
location.bandId,
|
||||||
|
location.position,
|
||||||
|
location.rawScale,
|
||||||
|
location.rawValue,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`result.locations`는 입력 band별 raw map의 local peak를 flat array로 담는다. 각 band
|
`result.locations`는 입력 band별 raw map의 local peak를 flat array로 담는다. 각 band
|
||||||
안에서는 power가 강한 순서이며 항목에는 `bandId`, band 내 `rank`, scan
|
안에서는 `rawValue`가 큰 순서이며 항목에는 `bandId`, band 내 `rank`, scan `index`,
|
||||||
`index`, `position`과 `rawPower`가 있다. 기본 threshold는 해당 band 최강
|
`position`, `rawValue`, `rawScale`이 있다. DAS의 기존 `rawPower` 필드는 호환 alias로 유지된다.
|
||||||
peak의 50%, 최소 peak 간격은 scan cell 대각선, 최대 검출 수는 band당 8개다. 여러 대역을
|
Score 결과에서는 `rawValue`를 공통 필드로 읽고, `rawScore`가 포함된 peak 객체에서는 같은 값의
|
||||||
사용한다면 `bandId`로 묶어 해석한다.
|
score alias로 사용할 수 있다. 기본 threshold는 해당 band 최강 peak의 50%, 최소 peak 간격은
|
||||||
|
scan cell 대각선, 최대 검출 수는 band당 8개다. 여러 대역을 사용한다면 `bandId`로 묶어 해석한다.
|
||||||
|
|
||||||
`peakDetection`은 후처리 위치 목록만 바꾸며 `result.bands[n].rawMap`과
|
`peakDetection`은 후처리 위치 목록만 바꾸며 `result.bands[n].rawMap`과
|
||||||
`displayMap`은 그대로 보존한다. 같은 대역의 두 음원이 main lobe보다 가까우면 local
|
`displayMap`은 그대로 보존한다. 같은 대역의 두 음원이 main lobe보다 가까우면 local
|
||||||
peak가 하나로 합쳐질 수 있고, threshold를 낮추면 sidelobe 후보도 늘 수 있다.
|
peak가 하나로 합쳐질 수 있고, threshold를 낮추면 sidelobe 후보도 늘 수 있다.
|
||||||
`sampleCount`와 `duration`도 결과에 함께 반환된다.
|
`sampleCount`와 `duration`도 결과에 함께 반환된다.
|
||||||
|
|
||||||
Block 결과의 `processingTimeMs`는 DAS 계산과 local-peak 검출에 걸린 monotonic wall
|
Block 결과의 `processingTimeMs`는 선택한 위치 추정 계산과 local-peak 검출에 걸린 monotonic wall
|
||||||
time이다. capture, adapter 변환과 결과 rendering 시간은 포함하지 않으므로 end-to-end latency는
|
time이다. capture, adapter 변환과 결과 rendering 시간은 포함하지 않으므로 end-to-end latency는
|
||||||
호출자가 별도로 측정한다.
|
호출자가 별도로 측정한다.
|
||||||
|
|
||||||
@@ -168,13 +276,14 @@ time이다. capture, adapter 변환과 결과 rendering 시간은 포함하지
|
|||||||
|
|
||||||
## 연속 chunk 처리
|
## 연속 chunk 처리
|
||||||
|
|
||||||
`StreamingDasLocalizer` 또는 같은 factory인 `createStreamingLocalizer`는 고정 용량
|
`StreamingLocalizer`는 알고리즘 중립 이름이며 기존 `StreamingDasLocalizer` class의 export alias다.
|
||||||
ring buffer와 분석 workspace를 갖는다.
|
오래된 이름은 호환을 위해 유지된다. 두 이름과 `createStreamingLocalizer` factory는 모두 선택한
|
||||||
|
`algorithm`에 맞는 고정 용량 ring buffer와 분석 workspace를 만든다.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { createStreamingLocalizer } from "./acoustics-core/realtime-localizer.js";
|
import { StreamingLocalizer } from "./acoustics-core/realtime-localizer.js";
|
||||||
|
|
||||||
const localizer = createStreamingLocalizer({
|
const localizer = new StreamingLocalizer({
|
||||||
sampleRate: 48_000,
|
sampleRate: 48_000,
|
||||||
array,
|
array,
|
||||||
scan: {
|
scan: {
|
||||||
@@ -190,6 +299,8 @@ const localizer = createStreamingLocalizer({
|
|||||||
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
||||||
],
|
],
|
||||||
stft: { fftSize: 512, hopSize: 256 },
|
stft: { fftSize: 512, hopSize: 256 },
|
||||||
|
algorithm: "das-phat",
|
||||||
|
phatRelativeFloor: 1e-6,
|
||||||
analysisWindowSamples: 4_800,
|
analysisWindowSamples: 4_800,
|
||||||
analysisHopSamples: 2_400,
|
analysisHopSamples: 2_400,
|
||||||
maximumBufferedSamples: 19_200,
|
maximumBufferedSamples: 19_200,
|
||||||
@@ -224,6 +335,11 @@ async function analysisLoop(signal) {
|
|||||||
`deadlineMs = analysisHopSamples / sampleRate × 1000`과
|
`deadlineMs = analysisHopSamples / sampleRate × 1000`과
|
||||||
`deadlineMet = processingTimeMs <= deadlineMs`를 반환한다.
|
`deadlineMet = processingTimeMs <= deadlineMs`를 반환한다.
|
||||||
|
|
||||||
|
`deadlineMet`는 완료된 한 창의 위치 추정 시간이 hop 예산 안이었는지를 나타내는 측정값이지,
|
||||||
|
해당 구성이 실시간이라는 사전 보장이 아니다. JIT warm-up, GC, 다른 thread의 부하를 포함해 목표
|
||||||
|
장치에서 연속 실행을 측정해야 한다. 이 값은 capture·transport·rendering을 포함하지 않으므로 전체
|
||||||
|
시스템 deadline은 adapter 경계에서 따로 계측한다.
|
||||||
|
|
||||||
## 지연과 backpressure 조정
|
## 지연과 backpressure 조정
|
||||||
|
|
||||||
서로 다른 hop이 두 층에 있다.
|
서로 다른 hop이 두 층에 있다.
|
||||||
@@ -268,18 +384,42 @@ async function analysisLoop(signal) {
|
|||||||
|
|
||||||
입력 retained byte는
|
입력 retained byte는
|
||||||
`채널 수 × (maximumBufferedSamples + analysisWindowSamples) × 4`이며 할당 전에 검사한다.
|
`채널 수 × (maximumBufferedSamples + analysisWindowSamples) × 4`이며 할당 전에 검사한다.
|
||||||
계획은 거리 행렬, bin calibration, Hann window, Float64 FFT workspace와 임시 map을 재사용한다.
|
모든 계획은 거리 행렬과 STFT workspace를 재사용한다. DAS 계열은 bin calibration, Hann window,
|
||||||
기본 retained data가 `maximumPlanBytes`를 넘으면 계획 생성을 거절한다. 전체 steering
|
임시 map과 steering cache를, GCC-PHAT는 선택 bin metadata, reference mic와 correlation workspace를
|
||||||
matrix가 64 MiB 또는 계획 전체 한도를 넘으면 선택 bin 앞쪽부터 예산에 들어가는 만큼만 cache하고
|
재사용한다. 기본 retained data가 `maximumPlanBytes`를 넘으면 할당 전에 계획 생성을 거절한다.
|
||||||
나머지는 고정 microphone workspace에서 필요할 때 계산한다.
|
Plan 없는 GCC 단발 분석도 거리 행렬 할당 전에 전체 working set을 `maximumWorkingBytes`와 비교한다.
|
||||||
|
DAS의 전체 steering matrix가 64 MiB 또는 계획 전체 한도를 넘으면 선택 bin 앞쪽부터 예산에 들어가는
|
||||||
|
만큼만 cache하고 나머지는 고정 microphone workspace에서 필요할 때 계산한다.
|
||||||
|
|
||||||
192채널, 50×50 scan, 선택 bin 2개를 같은 계획으로 10회 분석하는 기준에서 구현상 거리 계산은
|
기존 DAS 호환 경로에서 192채널, 50×50 scan, 선택 bin 2개를 같은 계획으로 10회 분석하면 거리 계산은
|
||||||
4,800,000회에서 480,000회, steering point–microphone pair는 9,600,000회에서 960,000회로
|
4,800,000회에서 480,000회, steering point–microphone pair는 9,600,000회에서 960,000회로
|
||||||
줄어든다. 17,280,000회의 `sin/cos` 호출을 피하고 약 16.5 MiB를 유지한다. 자동 테스트는
|
줄어든다. 17,280,000회의 `sin/cos` 호출을 피하고 약 16.5 MiB를 유지한다. 자동 테스트는
|
||||||
부분 cache와 cache 없음의 raw/display `Float32` map 모든 원소가 bit-exact임을 확인한다.
|
부분 cache와 cache 없음의 raw/display `Float32` map 모든 원소가 bit-exact임을 확인한다.
|
||||||
각 결과의 `analysisCache`에는 cache된 bin capacity와 실제 cached/uncached 사용,
|
각 결과의 `analysisCache`에는 공통 거리·STFT 통계와 알고리즘별 작업량이 들어간다. DAS 계열은
|
||||||
거리·steering pair, STFT transform·FFT butterfly·DAS complex MAC, workspace allocation·reuse
|
cached/uncached steering pair, FFT butterfly와 complex MAC을, GCC-PHAT는 cross-spectrum
|
||||||
수가 들어가므로 설정별 최적화 효과를 계측할 수 있다.
|
operation, pair별 IFFT, scan lookup과 correlation workspace reuse를 기록한다.
|
||||||
|
|
||||||
|
연산량을 비교할 때 다음 기호를 사용한다.
|
||||||
|
|
||||||
|
- `P`: scan point 수
|
||||||
|
- `M`: microphone 수
|
||||||
|
- `T`: 한 분석창의 STFT frame 수
|
||||||
|
- `F`: 선택한 고유 FFT bin 수
|
||||||
|
- `F_b`: band `b`의 bin 수, `B`: band 수
|
||||||
|
- `N`: `fftSize`
|
||||||
|
|
||||||
|
DAS와 DAS-PHAT의 지배적인 steering 누산은 대략 `P × M × T × F` complex MAC이다. PHAT
|
||||||
|
정규화가 추가되지만 scan 차수는 같다. GCC-PHAT는 모든 mic의 forward STFT를 한 번 수행한 뒤
|
||||||
|
reference pair `M-1`개에 대해 다음 작업을 수행한다.
|
||||||
|
|
||||||
|
- magnitude 최대값 pass와 PHAT 누산 pass:
|
||||||
|
`2 × (M-1) × T × ΣF_b` cross-spectrum operation
|
||||||
|
- 각 pair·band의 길이 `N` correlation IFFT: `(M-1) × B`회
|
||||||
|
- 각 scan point의 fractional lag lookup: `P × (M-1) × B`회
|
||||||
|
|
||||||
|
따라서 GCC-PHAT의 scan lookup은 DAS의 `P × M × T × F`보다 작을 수 있지만 공짜는 아니다.
|
||||||
|
Forward STFT는 그대로 필요하고, 작은 grid·큰 `N`·많은 band에서는 pair별 IFFT나 2-pass cross
|
||||||
|
spectrum이 지배할 수 있다. `workload`와 실제 `processingTimeMs`를 함께 비교한다.
|
||||||
|
|
||||||
실시간 목표를 맞추는 조정 순서는 보통 다음과 같다.
|
실시간 목표를 맞추는 조정 순서는 보통 다음과 같다.
|
||||||
|
|
||||||
@@ -293,15 +433,15 @@ matrix가 64 MiB 또는 계획 전체 한도를 넘으면 선택 bin 앞쪽부
|
|||||||
7. capture와 분석을 별도 Worker/thread에 두고 결과만 UI 또는 제어 loop로 전달한다.
|
7. capture와 분석을 별도 Worker/thread에 두고 결과만 UI 또는 제어 loop로 전달한다.
|
||||||
|
|
||||||
캐시 최적화와 위 수치는 반복 계산 감소의 근거이지 192채널·50×50 또는 다른 구성이 실시간이라는
|
캐시 최적화와 위 수치는 반복 계산 감소의 근거이지 192채널·50×50 또는 다른 구성이 실시간이라는
|
||||||
보장이 아니다. 마이크 수, scan point, 선택 bin, STFT frame에 따른 주연산은 여전히 대략
|
보장이 아니다. `deadlineMisses` 또는 `droppedSamples`가 누적되면 grid·band bin·FFT/분석창 또는
|
||||||
`O(P × M × F × T)`다. `deadlineMisses` 또는 `droppedSamples`가 누적되면
|
update rate를 줄여야 한다. 평균 한 번만 재지 말고 목표 장치의 실제 입력으로 warm-up 뒤 충분히 긴
|
||||||
grid·band bin·FFT/분석창 또는 update rate를 줄여야 한다. deadline은 위치추정 처리량 판정이며
|
구간의 최대값과 상위 percentile을 측정한다. Capture와 출력까지 포함하는 시스템 deadline은
|
||||||
capture와 출력까지 포함하는 시스템 deadline은 adapter에서 별도로 검증한다.
|
adapter에서 별도로 검증한다.
|
||||||
|
|
||||||
## 취소와 오류 복구
|
## 취소와 오류 복구
|
||||||
|
|
||||||
`localizeMultichannel`과 `analyzeAvailable`에 `AbortSignal`을 전달하면 STFT와
|
`localizeMultichannel`과 `analyzeAvailable`에 `AbortSignal`을 전달하면 STFT와
|
||||||
DAS batch 경계에서 `AbortError`를 발생시키고 계획 lock을 해제한다.
|
알고리즘별 scan/correlation batch 경계에서 `AbortError`를 발생시키고 계획 lock을 해제한다.
|
||||||
|
|
||||||
Streaming 분석이 취소되거나 실패하면 `failedAnalyses`가 증가하지만 해당 hop을
|
Streaming 분석이 취소되거나 실패하면 `failedAnalyses`가 증가하지만 해당 hop을
|
||||||
소비하지 않는다. 실패한 창은 별도 analysis workspace에 보존되며, 다음
|
소비하지 않는다. 실패한 창은 별도 analysis workspace에 보존되며, 다음
|
||||||
@@ -329,4 +469,4 @@ hop을 commit하고 sequence를 증가시킨다.
|
|||||||
|
|
||||||
코어 뒤에서는 `locations`를 제어에 바로 쓰기 전에 현장 데이터로 검출 임계값, false peak,
|
코어 뒤에서는 `locations`를 제어에 바로 쓰기 전에 현장 데이터로 검출 임계값, false peak,
|
||||||
latency와 위치 오차를 검증해야 한다. 현재 `locations`는 통계적 신뢰구간이 아니라 각 band
|
latency와 위치 오차를 검증해야 한다. 현재 `locations`는 통계적 신뢰구간이 아니라 각 band
|
||||||
DAS map에서 threshold와 거리 억제를 통과한 grid local peak 후보들이다.
|
위치 map에서 threshold와 거리 억제를 통과한 grid local peak 후보들이다.
|
||||||
|
|||||||
@@ -6,7 +6,55 @@
|
|||||||
- 자유음장 직접음과 선택적 저비용 shoebox multipath
|
- 자유음장 직접음과 선택적 저비용 shoebox multipath
|
||||||
- zero-padded FFT 전달함수 기반 fractional sample delay와 마이크 주파수 응답
|
- zero-padded FFT 전달함수 기반 fractional sample delay와 마이크 주파수 응답
|
||||||
- radix-2 FFT, Hann STFT와 선택 bin 추출
|
- radix-2 FFT, Hann STFT와 선택 bin 추출
|
||||||
- scan grid 거리 cache 및 conventional frequency-domain DAS
|
- scan grid 거리 cache 및 DAS·DAS-PHAT·GCC-PHAT 위치 추정
|
||||||
|
|
||||||
|
## 위치 추정 알고리즘
|
||||||
|
|
||||||
|
`localization-algorithms.js`의 registry와 `localization.js`의 generic API가 다음 세 경로를
|
||||||
|
공통 interface로 제공합니다.
|
||||||
|
|
||||||
|
| `algorithm` | 계산 | raw scale | backend |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `das` | conventional frequency-domain delay-and-sum | `power` | CPU, WebGPU |
|
||||||
|
| `das-phat` | 채널 spectrum을 phase-only로 만든 DAS | `score` | CPU, WebGPU |
|
||||||
|
| `gcc-phat` | 하나의 reference mic와 나머지 mic의 GCC-PHAT 지연 scan | `score` | CPU only |
|
||||||
|
|
||||||
|
Portable API에서는 top-level `algorithm`으로 선택합니다. 생략하면 기존과 같은 `das`이며, 낮은
|
||||||
|
수준의 generic API는 `experiment.beamforming.algorithm`을 사용합니다.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
createLocalizationPlan,
|
||||||
|
localizeMultichannel,
|
||||||
|
} from "./packages/acoustics-core/realtime-localizer.js";
|
||||||
|
|
||||||
|
const plan = createLocalizationPlan({
|
||||||
|
...commonConfig, // sampleRate, array, scan, bands, stft
|
||||||
|
algorithm: "gcc-phat", // "das" | "das-phat" | "gcc-phat"
|
||||||
|
phatFloorRatio: 1e-6,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 반복 분석에서도 같은 plan을 재사용합니다.
|
||||||
|
const result = await localizeMultichannel({ plan, channels });
|
||||||
|
```
|
||||||
|
|
||||||
|
`das-phat`의 `phatRelativeFloor`와 `gcc-phat`의 `phatFloorRatio`는 모두 0~1의 상대
|
||||||
|
크기 floor이며 기본값은 `1e-6`입니다. GCC-PHAT는 `phatRelativeFloor`도 호환 alias로
|
||||||
|
받지만 새 코드에서는 알고리즘별 이름을 권장합니다. PHAT 경로는 mic gain을 위치 score에
|
||||||
|
사용하지 않고 알려진 mic·frequency-response phase만 보정합니다.
|
||||||
|
|
||||||
|
GCC-PHAT는 단일 tone보다 여러 FFT bin에 에너지가 있는 broadband 입력을 권장합니다. 하나의
|
||||||
|
band에 선택된 bin이 8개 미만이면 코어는 계산을 허용하지만 주기적 모호성과 ghost peak를 직접
|
||||||
|
검증해야 합니다. 또한 reference pair의 scan 전체 최대 절대 기하 지연이 `fftSize / 2` sample을
|
||||||
|
넘으면 circular correlation alias를 피하기 위해 plan 생성을 거절합니다. 이때는 `fftSize`를
|
||||||
|
늘리거나 배열·scan 기하를 조정합니다.
|
||||||
|
|
||||||
|
각 band의 `rawScale`은 `power` 또는 `score`입니다. `rawValue`가 scale에 무관한 표준 peak
|
||||||
|
값이며, `rawPower`는 `power`, `rawScore`는 `score`일 때만 쓰는 편의 alias입니다. `score`는
|
||||||
|
확률·신뢰도·SPL이 아니고 동일 알고리즘·설정 안에서 상대 peak를 비교하는 비교정 값입니다.
|
||||||
|
`power`도 입력과 calibration이 절대 단위로 교정되지 않았다면 물리적 W 또는 Pa²로 해석하지 않습니다.
|
||||||
|
GCC-PHAT score는 pair 수, band coefficient 수와 IFFT 크기로 정규화한 0–1 양의 상관 응답이라
|
||||||
|
scan 범위와 마이크 수에 의한 단순 재척도화는 피하지만, 여전히 확률로 보정된 confidence는 아닙니다.
|
||||||
|
|
||||||
## 실측 다채널 스트림 위치 추정
|
## 실측 다채널 스트림 위치 추정
|
||||||
|
|
||||||
@@ -15,6 +63,10 @@
|
|||||||
디렉터리를 그대로 복사해 사용할 수 있습니다. 채널 순서는 `array.microphones` 순서와 같아야 하고
|
디렉터리를 그대로 복사해 사용할 수 있습니다. 채널 순서는 `array.microphones` 순서와 같아야 하고
|
||||||
각 chunk는 동일 길이의 `Float32Array` 목록이어야 합니다.
|
각 chunk는 동일 길이의 `Float32Array` 목록이어야 합니다.
|
||||||
|
|
||||||
|
`StreamingLocalizer`는 알고리즘 중립 class 이름입니다. 기존 `StreamingDasLocalizer`와 같은 class의
|
||||||
|
export alias이므로 오래된 import도 그대로 동작하며, `createStreamingLocalizer()` factory도 세
|
||||||
|
알고리즘을 모두 지원합니다.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { createStreamingLocalizer } from "./packages/acoustics-core/realtime-localizer.js";
|
import { createStreamingLocalizer } from "./packages/acoustics-core/realtime-localizer.js";
|
||||||
|
|
||||||
@@ -24,6 +76,7 @@ const localizer = createStreamingLocalizer({
|
|||||||
scan: { xMin: -1, xMax: 1, yMin: -1, yMax: 1, z: 2, columns: 50, rows: 50 },
|
scan: { xMin: -1, xMax: 1, yMin: -1, yMax: 1, z: 2, columns: 50, rows: 50 },
|
||||||
bands: [{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" }],
|
bands: [{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" }],
|
||||||
stft: { fftSize: 512, hopSize: 256 },
|
stft: { fftSize: 512, hopSize: 256 },
|
||||||
|
algorithm: "das", // 호환 기본값. "das-phat" 또는 "gcc-phat"도 선택할 수 있습니다.
|
||||||
maxCompensationDb: 24,
|
maxCompensationDb: 24,
|
||||||
peakDetection: { thresholdRatio: 0.5, maximumDetections: 8 },
|
peakDetection: { thresholdRatio: 0.5, maximumDetections: 8 },
|
||||||
analysisWindowSamples: 4_800,
|
analysisWindowSamples: 4_800,
|
||||||
@@ -38,15 +91,17 @@ localizer.append(channels);
|
|||||||
// Analysis loop: 호출마다 설정된 상한 이하의 map만 반환합니다.
|
// Analysis loop: 호출마다 설정된 상한 이하의 map만 반환합니다.
|
||||||
const results = await localizer.analyzeAvailable({ signal: abortController.signal });
|
const results = await localizer.analyzeAvailable({ signal: abortController.signal });
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
const { position, rawPower } = result.locations[0];
|
const { position, rawValue, rawScale } = result.locations[0];
|
||||||
drawMarker(position, rawPower, result.centerTime);
|
drawMarker(position, rawValue, rawScale, result.centerTime);
|
||||||
if (!result.deadlineMet) reportOverload(result.processingTimeMs, result.deadlineMs);
|
if (!result.deadlineMet) reportOverload(result.processingTimeMs, result.deadlineMs);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`locations`는 band 순서, 같은 band 안에서는 raw power 내림차순의 평평한 목록입니다. 각 항목은
|
`locations`는 band 순서, 같은 band 안에서는 `rawValue` 내림차순의 평평한 목록입니다. 각 항목은
|
||||||
기존 `{ bandId, index, position, rawPower }`에 `rank`를 더하며 같은 band의 여러 local peak를
|
`{ bandId, rank, index, position, rawValue, rawScale }`이며 같은 band의 여러 local peak를 포함할
|
||||||
포함할 수 있습니다. `peakDetection.thresholdRatio` 기본값은 최강 peak의 0.5배,
|
수 있습니다. 기존 DAS 결과의 `rawPower` 별칭은 그대로 유지됩니다. PHAT score는 `rawValue`와
|
||||||
|
`rawScale`을 기준으로 읽고, score peak 객체에 포함된 경우 `rawScore`를 같은 값의 별칭으로 씁니다.
|
||||||
|
`peakDetection.thresholdRatio` 기본값은 최강 peak의 0.5배,
|
||||||
`minimumPeakDistanceM` 기본값은 scan cell 대각선, `maximumDetections` 기본값은 8입니다.
|
`minimumPeakDistanceM` 기본값은 scan cell 대각선, `maximumDetections` 기본값은 8입니다.
|
||||||
기존처럼 `locations[0]`만 읽으면 최강 후보를 그대로 얻습니다.
|
기존처럼 `locations[0]`만 읽으면 최강 후보를 그대로 얻습니다.
|
||||||
|
|
||||||
@@ -55,10 +110,13 @@ Streaming 계산이 중단되거나 실패하면 해당 분석창과 sequence를
|
|||||||
`onResult` callback의 예외는 `failedAnalyses`에 포함하지 않습니다. 계산 중 capture overflow가 나면
|
`onResult` callback의 예외는 `failedAnalyses`에 포함하지 않습니다. 계산 중 capture overflow가 나면
|
||||||
ring의 오래된 sample은 평소와 같이 drop telemetry에 기록됩니다.
|
ring의 오래된 sample은 평소와 같이 drop telemetry에 기록됩니다.
|
||||||
|
|
||||||
한 블록 결과의 `processingTimeMs`는 DAS와 local-peak 검출에 걸린 실제 시간을 기록합니다. Streaming
|
한 블록 결과의 `processingTimeMs`는 선택한 위치 추정 알고리즘과 local-peak 검출에 걸린 실제 시간을
|
||||||
|
기록합니다. Streaming
|
||||||
결과는 `deadlineMs = analysisHopSamples / sampleRate × 1000`과 `deadlineMet`을 더하며,
|
결과는 `deadlineMs = analysisHopSamples / sampleRate × 1000`과 `deadlineMet`을 더하며,
|
||||||
`getState()`는 최근/최대 처리 시간과 `deadlineMisses` 누계를 제공합니다. `deadlineMisses` 또는
|
`getState()`는 최근/최대 처리 시간과 `deadlineMisses` 누계를 제공합니다. `deadlineMisses` 또는
|
||||||
`droppedSamples`가 증가하면 grid·대역 bin·분석창·update rate를 장치 성능에 맞게 줄여야 합니다.
|
`droppedSamples`가 증가하면 grid·대역 bin·분석창·update rate를 장치 성능에 맞게 줄여야 합니다.
|
||||||
|
이 deadline 비교는 실시간 성능 보장이 아니라 완료된 창의 측정값입니다. 목표 장치에서 warm-up을 거친
|
||||||
|
지속 부하를 직접 측정하고, capture·adapter·출력을 포함한 end-to-end deadline은 별도로 검증해야 합니다.
|
||||||
|
|
||||||
깊은 응답 notch의 역필터가 sensor noise까지 폭증시키지 않도록 inverse response의 양의 boost는 기본
|
깊은 응답 notch의 역필터가 sensor noise까지 폭증시키지 않도록 inverse response의 양의 boost는 기본
|
||||||
24 dB로 제한합니다. Experiment의 `beamforming.maxCompensationDb` 또는 portable plan의 top-level
|
24 dB로 제한합니다. Experiment의 `beamforming.maxCompensationDb` 또는 portable plan의 top-level
|
||||||
@@ -71,16 +129,27 @@ cache가 나중에 `maximumPlanBytes`를 넘지 않습니다.
|
|||||||
buffer byte 수를 돌려주므로 capture adapter가 지연을 감시할 수 있습니다. 실제 장치의 clock,
|
buffer byte 수를 돌려주므로 capture adapter가 지연을 감시할 수 있습니다. 실제 장치의 clock,
|
||||||
channel framing과 transport는 하드웨어별 adapter 책임이며 이 모듈은 그 다음 단계부터 시작합니다.
|
channel framing과 transport는 하드웨어별 adapter 책임이며 이 모듈은 그 다음 단계부터 시작합니다.
|
||||||
|
|
||||||
반복 CPU 분석 계획은 거리 행렬, bin calibration, Hann window, Float64 FFT workspace, 임시 bin map과
|
반복 CPU 분석 계획은 공통 거리 행렬과 STFT workspace를 재사용합니다. DAS 계열은 bin calibration,
|
||||||
예산 내의 Float64 steering matrix를 재사용합니다. 예를 들어 192채널·50×50·2 bins를 10회 분석하면
|
Hann window, 임시 bin map과 예산 내의 Float64 steering matrix를, GCC-PHAT는 reference 선택과
|
||||||
|
correlation workspace를 추가로 유지합니다. 같은 plan을 동시에 두 분석에 쓰지 말고 설정이나 알고리즘이
|
||||||
|
바뀌면 새 plan을 만듭니다. 예를 들어 DAS로 192채널·50×50·2 bins를 10회 분석하면
|
||||||
거리 계산은 4,800,000회에서 480,000회로, steering point/microphone pair는 9,600,000회에서
|
거리 계산은 4,800,000회에서 480,000회로, steering point/microphone pair는 9,600,000회에서
|
||||||
960,000회로 줄어듭니다(sin/cos 호출 17,280,000회 회피). 이 경우 약 16.5 MiB를 유지합니다.
|
960,000회로 줄어듭니다(sin/cos 호출 17,280,000회 회피). 이 경우 약 16.5 MiB를 유지합니다.
|
||||||
|
|
||||||
기본 64 MiB보다 전체 wide-band steering matrix가 크더라도 cache 전체를 끄지 않습니다. 선택 bin
|
기본 64 MiB보다 전체 wide-band steering matrix가 크더라도 cache 전체를 끄지 않습니다. 선택 bin
|
||||||
앞쪽부터 예산에 들어가는 만큼만 Float64로 유지하고 나머지는 고정 microphone workspace에서 계산합니다.
|
앞쪽부터 예산에 들어가는 만큼만 Float64로 유지하고 나머지는 고정 microphone workspace에서 계산합니다.
|
||||||
`analysisCache`는 cached bin capacity, uncached 사용 횟수·pair 수, STFT transform·FFT butterfly·DAS
|
`analysisCache`는 알고리즘별 실제 작업을 제공합니다. DAS 계열은 cached bin capacity,
|
||||||
complex MAC 수와 실제 workspace allocation/reuse 수를 제공합니다. 자동 테스트는 부분 cache와
|
uncached steering pair, STFT transform·FFT butterfly·complex MAC을, GCC-PHAT는 STFT/IFFT,
|
||||||
cache 없음 사이 raw/display Float32 map의 전 요소 bit-exact 일치를 고정합니다.
|
2-pass cross-spectrum operation, scan lookup과 correlation workspace reuse를 기록합니다.
|
||||||
|
|
||||||
|
`P`를 scan point 수, `M`을 mic 수, `T`를 STFT frame 수, `F`를 선택한 고유 bin 수,
|
||||||
|
`B`를 band 수, `N`을 `fftSize`라 하면 DAS의 주 scan 연산은 대략
|
||||||
|
`P × M × T × F` complex MAC입니다. GCC-PHAT는 forward STFT에 더해 reference pair `M-1`개마다
|
||||||
|
band bin을 두 번 순회하는 cross spectrum, `(M-1) × B`회의 길이 `N` IFFT,
|
||||||
|
`P × (M-1) × B`회의 fractional correlation lookup을 수행합니다. band별 bin 수를 `F_b`라 하면
|
||||||
|
cross-spectrum 항목 수는 구현의 두 pass를 포함해 `2 × (M-1) × T × ΣF_b`입니다. 따라서 GCC가
|
||||||
|
scan MAC을 줄여도 작은 grid에서는 forward STFT와 pair별 IFFT가 전체 시간을 지배할 수 있으므로
|
||||||
|
두 알고리즘 모두 실제 목표 장치에서 측정해야 합니다.
|
||||||
|
|
||||||
## 이동 음원과 분석 시간창
|
## 이동 음원과 분석 시간창
|
||||||
|
|
||||||
@@ -94,25 +163,30 @@ seed 기반 noise index, audio asset 재생 위치와 ambient가 전체 timeline
|
|||||||
|
|
||||||
## Beam spread 의미
|
## Beam spread 의미
|
||||||
|
|
||||||
Peak의 `beamSpread`는 half-power 연결 성분을 power 가중한 공간 covariance(`covarianceM2`, m²)와 그
|
Peak의 `beamSpread`는 raw map의 peak 주변 연결 성분을 가중한 공간 covariance(`covarianceM2`, m²)와
|
||||||
RMS 주축 ellipse로 요약한 빔 폭입니다. 가우시안 확률 모델, 위치 확률 또는 신뢰구간으로 보정된 값이
|
그 RMS 주축 ellipse로 요약한 폭입니다. `power` map은 half-power/power-weighted,
|
||||||
아니며 `calibrated: false`를 유지합니다.
|
`score` map은 half-maximum/score-weighted 규칙을 사용합니다. 어느 쪽도 가우시안 확률 모델,
|
||||||
|
위치 확률 또는 신뢰구간으로 보정된 값이 아니며 `calibrated: false`를 유지합니다.
|
||||||
|
|
||||||
FFT는 `X[k] = Σ x[n] exp(-j2πkn/N)` 규약을 사용합니다. 마이크 신호의 전파 phase
|
FFT는 `X[k] = Σ x[n] exp(-j2πkn/N)` 규약을 사용합니다. 마이크 신호의 전파 phase
|
||||||
`exp(-j2πfr/c)`를 정렬하기 위해 DAS steering은 `exp(+j2πfr/c)`를 곱합니다. 단일 tone의
|
`exp(-j2πfr/c)`를 정렬하기 위해 DAS steering은 `exp(+j2πfr/c)`를 곱합니다. 단일 tone의
|
||||||
ground-truth 위치에서 peak가 생기는 회귀 테스트로 이 부호를 고정합니다.
|
ground-truth 위치에서 peak가 생기는 회귀 테스트로 이 부호를 고정합니다.
|
||||||
|
|
||||||
마이크 `sensitivityDb`와 `phaseOffsetDeg`는 수신 channel에 편차로 적용하고, DAS에서는 알려진
|
마이크 `sensitivityDb`와 `phaseOffsetDeg`는 수신 channel에 편차로 적용합니다. Conventional DAS는
|
||||||
calibration 값의 역 gain/phase로 보정합니다. raw power map과 표시용 normalized map은 서로 다른
|
알려진 calibration의 역 gain/phase를 모두 보정하고, DAS-PHAT와 GCC-PHAT는 amplitude gain을 무시한
|
||||||
buffer로 보존합니다. bin spectrum은 제한된 batch로 처리합니다. cooperative yield는 지원 환경에서
|
채 알려진 phase만 보정합니다. raw `power`/`score` map과 표시용 normalized map은 서로 다른 buffer로
|
||||||
|
보존합니다. bin spectrum은 제한된 batch로 처리합니다. cooperative yield는 지원 환경에서
|
||||||
`scheduler.yield()`, 그 외에는 `MessageChannel`을 사용하고 timer task에도 주기적으로 기회를 주므로
|
`scheduler.yield()`, 그 외에는 `MessageChannel`을 사용하고 timer task에도 주기적으로 기회를 주므로
|
||||||
진행 callback과 `AbortSignal` 취소를 유지하면서 연속 `setTimeout(0)` clamp를 피합니다. portable
|
진행 callback과 `AbortSignal` 취소를 유지하면서 연속 `setTimeout(0)` clamp를 피합니다. portable
|
||||||
plan의 기본 batch는 point 256개·STFT transform 128개이며 `computeOptions`로 조정할 수 있습니다.
|
plan의 기본 point batch는 DAS 계열 256개, GCC-PHAT 4,096개이고 STFT transform batch는
|
||||||
|
128개입니다. GCC-PHAT의 두 cross-spectrum pass도 16,384 operation마다 양보합니다.
|
||||||
|
`pointBatchSize`, `stftTransformBatchSize`, `crossSpectrumBatchSize`를
|
||||||
|
`computeOptions`로 조정할 수 있습니다.
|
||||||
|
|
||||||
마이크별 `frequencyResponse`는 2~64개의 `{ frequencyHz, gainDb, phaseDeg? }` 점으로 정의합니다.
|
마이크별 `frequencyResponse`는 2~64개의 `{ frequencyHz, gainDb, phaseDeg? }` 점으로 정의합니다.
|
||||||
`interpolateFrequencyResponse`는 dB와 wrapped phase를 구간 선형 보간하고 측정 범위 밖에서는 가장
|
`interpolateFrequencyResponse`는 dB와 wrapped phase를 구간 선형 보간하고 측정 범위 밖에서는 가장
|
||||||
가까운 끝점을 사용합니다. 합성 시 기존 sensitivity/phase 편차에 이 응답을 추가하며, CPU DAS는
|
가까운 끝점을 사용합니다. 합성 시 기존 sensitivity/phase 편차에 이 응답을 추가하며, CPU 위치 추정은
|
||||||
선택 FFT bin의 역응답을 calibration/steering cache에 포함합니다. WebGPU 경로는 GPU 전송 직전의
|
선택 FFT bin의 알고리즘별 역응답을 calibration에 포함합니다. WebGPU DAS 계열 경로는 GPU 전송 직전의
|
||||||
packed STFT에 같은 역응답을 적용합니다. `beamforming.compensateFrequencyResponse: false`는
|
packed STFT에 같은 역응답을 적용합니다. `beamforming.compensateFrequencyResponse: false`는
|
||||||
sensitivity/phase 보정은 유지한 채 곡선 보정만 꺼 robustness 비교를 재현합니다.
|
sensitivity/phase 보정은 유지한 채 곡선 보정만 꺼 robustness 비교를 재현합니다.
|
||||||
|
|
||||||
@@ -143,6 +217,9 @@ Scene의 `acoustics`를 생략하거나 `{ "model": "free-field" }`로 두면
|
|||||||
snapshot 합성은 전체 signal과 가장 늦은 sparse path를 포함하는 delay FFT working set을
|
snapshot 합성은 전체 signal과 가장 늦은 sparse path를 포함하는 delay FFT working set을
|
||||||
512 MiB로 제한합니다. 실측·장시간 입력은 위 streaming localizer의 bounded ring buffer로
|
512 MiB로 제한합니다. 실측·장시간 입력은 위 streaming localizer의 bounded ring buffer로
|
||||||
전체 녹음을 메모리에 보관하지 않고 처리할 수 있습니다. CPU analysis plan도 기본 512 MiB
|
전체 녹음을 메모리에 보관하지 않고 처리할 수 있습니다. CPU analysis plan도 기본 512 MiB
|
||||||
hard cap을 할당 전에 검사하며 steering cache는 별도의 64 MiB 안에서 가능한 bin만 유지합니다.
|
hard cap을 할당 전에 검사합니다. DAS steering cache는 별도의 64 MiB 안에서 가능한 bin만 유지하고,
|
||||||
|
GCC-PHAT는 거리·STFT·correlation workspace 전체를 plan 한도 안에서 검사합니다. Plan 없는 단발
|
||||||
|
GCC 분석도 거리 행렬을 만들기 전에 spectrum·calibration·output을 포함한 working set을 preflight합니다.
|
||||||
|
|
||||||
192채널·50×50 fixture는 브라우저 통합 테스트에서 실제 합성부터 DAS peak 검출까지 실행합니다.
|
192채널·50×50 fixture는 기존 DAS 호환 경로를 실제 합성부터 peak 검출까지 고정하며, 별도의 결정적
|
||||||
|
회귀 fixture가 DAS-PHAT와 GCC-PHAT의 score scale·lag 부호·plan 재사용을 검사합니다.
|
||||||
|
|||||||
@@ -17,13 +17,14 @@ Unit과 integration test가 같은 페이지에서 실행됩니다. WebGPU 장
|
|||||||
## 범위
|
## 범위
|
||||||
|
|
||||||
- `cpu-baseline.test.js`: 192채널·50×50 synthetic fixture의 CPU DAS와 위치 기준
|
- `cpu-baseline.test.js`: 192채널·50×50 synthetic fixture의 CPU DAS와 위치 기준
|
||||||
- `webgpu.test.js`: 실제 adapter가 있으면 CPU/GPU map 오차, peak와 강제 bin/point batching;
|
- `webgpu.test.js`: 실제 adapter가 있으면 DAS·DAS-PHAT CPU/GPU map 오차, peak와 강제 bin/point batching;
|
||||||
adapter가 없으면 Auto CPU fallback
|
adapter가 없으면 Auto CPU fallback
|
||||||
- `server.test.js`: 숨김 저장소 경로 차단, GET/HEAD 제한과 보안 response headers
|
- `server.test.js`: 숨김 저장소 경로 차단, GET/HEAD 제한과 보안 response headers
|
||||||
- `builder-ui.test.js`: 파일 선택 한 번으로 오디오 음원 생성, 이미지·오디오 연결, canvas 편집,
|
- `builder-ui.test.js`: 파일 선택 한 번으로 오디오 음원 생성, 이미지·오디오 연결, canvas 편집,
|
||||||
trajectory keyframe 편집, Preview WAV/Scene 다운로드, SHA 재연결과 잘못된 import 보존
|
trajectory keyframe 편집, Preview WAV/Scene 다운로드, SHA 재연결과 잘못된 import 보존
|
||||||
- `camera-ui.test.js`: Dedicated Worker CPU/WebGPU 실행, 취소, Result schema, rectangular/Fermat 비교;
|
- `camera-ui.test.js`: Dedicated Worker CPU/WebGPU 실행, 취소, Result schema, rectangular/Fermat와
|
||||||
이동 예제 로드, 8×8 CPU·2 Hz live map 준비, 복수 frame, scrub, 재생 시간 증가와 일시정지
|
DAS/DAS-PHAT 비교, GCC-PHAT CPU·협대역 제약; 이동 예제 로드, 8×8 CPU·2 Hz live map의
|
||||||
|
Auto→CPU fallback 뒤 공통 analysis plan 재사용, 복수 frame, scrub, 재생 시간 증가와 일시정지
|
||||||
- `workflow-ui.test.js`: Dataset Builder의 Scene JSON과 원본 assets를 Acoustic Camera에 넘겨
|
- `workflow-ui.test.js`: Dataset Builder의 Scene JSON과 원본 assets를 Acoustic Camera에 넘겨
|
||||||
Result JSON을 저장하는 end-to-end 흐름
|
Result JSON을 저장하는 end-to-end 흐름
|
||||||
|
|
||||||
|
|||||||
@@ -17,16 +17,22 @@ Unit과 integration module은 같은 browser runner에서 순서대로 실행됩
|
|||||||
|
|
||||||
## 범위
|
## 범위
|
||||||
|
|
||||||
- `contracts.test.js`: Array·Scene·Experiment·Result schema, 관계 검증, 안전한 asset 경로와 이동 fixture
|
- `contracts.test.js`: Array·Scene·Experiment·Result schema, algorithm·scale·beam-spread 관계 검증,
|
||||||
|
안전한 asset 경로와 이동 fixture
|
||||||
- `acoustics.test.js`: seed 재현성, 자유음장 전파, trajectory 보간, sample 정렬 시간창과
|
- `acoustics.test.js`: seed 재현성, 자유음장 전파, trajectory 보간, sample 정렬 시간창과
|
||||||
tone/noise/asset 절대 시간 연속성, calibration, STFT와 CPU DAS
|
tone/noise/asset 절대 시간 연속성, calibration, STFT, CPU DAS와 DAS-PHAT
|
||||||
|
- `gcc-phat.test.js`: reference 선택, near-field lag 부호, 광대역 source peak, alias·메모리
|
||||||
|
선할당 제한, 0–1 score bound·scan 범위 불변성과 geometry/STFT/IFFT workspace 재사용
|
||||||
|
- `localization.test.js`: 알고리즘 registry와 generic CPU/backend dispatcher, power/score
|
||||||
|
의미, portable GCC-PHAT block·streaming 경로
|
||||||
- `realtime-localizer.test.js`: 기존 CPU DAS와 bit-exact map 동등성, chunk 경계 독립성,
|
- `realtime-localizer.test.js`: 기존 CPU DAS와 bit-exact map 동등성, chunk 경계 독립성,
|
||||||
bounded ring/result batch, 취소와 geometry·steering cache 연산 절감
|
bounded ring/result batch, 취소와 geometry·steering cache 연산 절감
|
||||||
- `builder.test.js`: Builder scene model, source/asset·trajectory 조작, 오디오 크기와 WAV 사전 검증
|
- `builder.test.js`: Builder scene model, source/asset·trajectory 조작, 오디오 크기와 WAV 사전 검증
|
||||||
- `evaluation.test.js`: local peak와 검출 감도, truth matching, energy/sidelobe/main-lobe 및 비확률적
|
- `evaluation.test.js`: local peak와 검출 감도, truth matching, energy/sidelobe/main-lobe 및 비확률적
|
||||||
beam-spread covariance ellipse
|
beam-spread covariance ellipse
|
||||||
- `camera.test.js`: canonical input hash, workload 추정, 이동 timeline 계획·재생 보간, Result schema 검증
|
- `camera.test.js`: canonical input hash, workload 추정, 이동 timeline 계획·재생 보간, Result schema 검증
|
||||||
- `webgpu.test.js`: WGSL buffer packing, bin/point batching, 장치 한계와 typed CPU fallback 정책
|
- `webgpu.test.js`: WGSL buffer packing, DAS-PHAT phase normalization, bin/point batching,
|
||||||
|
장치 한계와 typed CPU fallback 정책
|
||||||
|
|
||||||
WebGPU unit test 대부분은 실제 GPU 없이 planner와 binary layout을 검증합니다. 실제 GPU 수치 일치는
|
WebGPU unit test 대부분은 실제 GPU 없이 planner와 binary layout을 검증합니다. 실제 GPU 수치 일치는
|
||||||
integration test에서 adapter가 있을 때 수행합니다.
|
integration test에서 adapter가 있을 때 수행합니다.
|
||||||
|
|||||||
Reference in New Issue
Block a user