docs: explain localization choices and cost
This commit is contained in:
+110
-14
@@ -11,8 +11,9 @@ Snapshot 한 번의 처리 순서는 다음과 같다.
|
||||
1. tone, noise 또는 audio asset으로 음원 신호를 만든다.
|
||||
2. 음원과 각 마이크 사이의 직접음 또는 희소 multipath 전달함수를 만든다.
|
||||
3. 마이크별 `sensitivityDb`, `phaseOffsetDeg`와 `frequencyResponse`를 수신 신호에 적용한다.
|
||||
4. 합성된 동기식 다채널 신호를 STFT하고 conventional DAS map을 계산한다.
|
||||
5. 설정에 따라 알려진 마이크 응답을 DAS에서 역보정하고 peak와 평가 지표를 구한다.
|
||||
4. 합성된 동기식 다채널 신호를 STFT하고 `beamforming.algorithm`으로 선택한 위치 추정
|
||||
알고리즘의 scan map을 계산한다.
|
||||
5. 알고리즘에 맞게 알려진 마이크 응답을 보정하고 map의 peak와 평가 지표를 구한다.
|
||||
|
||||
Scene의 `acoustics`를 생략하거나 `model: "free-field"`로 지정하면 기존 직접음 결과를
|
||||
유지한다. `model: "shoebox"`는 직육면체 방 안에서 경로 수가 제한된 근사를 추가한다.
|
||||
@@ -97,9 +98,91 @@ preset을 적용한다.
|
||||
각 source–microphone 직접 경로를 실제로 막을 때 하나씩 추가된다. 대략적인 합성 경로 예산은
|
||||
`음원 수 × 마이크 수 × 수신점당 최대 경로`다. Camera는 실행 전에 이 예산을 표시한다.
|
||||
|
||||
반사·tail을 늘리면 beamforming의 `O(scan points × microphones × selected bins × STFT frames)`
|
||||
뿐 아니라 신호 합성의 전달함수 누산도 늘어난다. 처음에는 50×50 grid와 자유음장으로 기준선을
|
||||
만들고, 같은 입력에서 preset을 하나씩 바꾸어 비교하는 것이 좋다.
|
||||
반사·tail을 늘리면 신호 합성의 전달함수 누산도 늘어난다. DAS 계열의 scan 누산은 대략
|
||||
`O(scan points × microphones × selected bins × STFT frames)`이고, GCC-PHAT는 pair별 상호
|
||||
상관을 만든 뒤 `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를 실제 마이크
|
||||
채널에 적용한다.
|
||||
|
||||
Experiment에서 `beamforming.compensateFrequencyResponse`를 생략하거나 `true`로 두면
|
||||
CPU와 WebGPU DAS가 선택 FFT bin에서 알려진 curve의 역 gain/phase를 적용한다. 응답 notch의
|
||||
무제한 역보정은 noise까지 크게 증폭할 수 있으므로 양의 보상 boost는
|
||||
`beamforming.maxCompensationDb`로 제한하며 기본값은 24 dB다. 허용 범위는 0–120 dB이고
|
||||
응답 peak를 줄이는 attenuation과 phase 보상은 이 boost 상한에 의해 잘리지 않는다.
|
||||
합성기는 알고리즘과 무관하게 sensitivity, 정적 phase offset과 frequency-response curve를 수신
|
||||
channel에 적용한다. 위치 추정에서의 역보정은 알고리즘별로 다르다.
|
||||
|
||||
- DAS는 sensitivity 역 gain과 정적 phase를 항상 보정한다. `compensateFrequencyResponse`를
|
||||
생략하거나 `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
|
||||
{
|
||||
@@ -147,8 +236,10 @@ CPU와 WebGPU DAS가 선택 FFT bin에서 알려진 curve의 역 gain/phase를
|
||||
```
|
||||
|
||||
Camera의 **마이크 주파수 응답 처리**에서 **측정 curve 적용 + 보정하지 않음**을 고르면 합성에는
|
||||
curve가 남고 DAS 역보정만 꺼진다. 같은 배열에서 보정 유무의 robustness를 비교할 때 사용한다.
|
||||
curve가 없는 마이크는 0 dB, 0°로 취급한다.
|
||||
curve가 남고 위치 추정의 response gain/phase 역보정만 꺼진다. DAS-PHAT와 GCC-PHAT는 여전히
|
||||
amplitude를 버리지만, curve가 신호 대 잡음과 relative floor 통과 여부에 준 영향까지 되돌리지는
|
||||
못한다. 같은 배열에서 알려진 response 보정 유무의 robustness를 비교할 때 사용한다. curve가 없는
|
||||
마이크는 0 dB, 0°로 취급한다.
|
||||
|
||||
## 결과에서 확인할 값
|
||||
|
||||
@@ -162,6 +253,10 @@ Result `signalStats`에는 다음 선택 필드가 들어간다.
|
||||
같은 입력과 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 측정치를 대신하지 않는다. 다음 항목은
|
||||
@@ -175,8 +270,9 @@ Result `signalStats`에는 다음 선택 필드가 들어간다.
|
||||
- preamp, anti-alias filter, ADC quantization, channel clock jitter·drift
|
||||
- 실제 장착 구조와 마이크 위치 공차
|
||||
|
||||
따라서 preset의 RT60이나 wall gain은 특정 방을 인증하는 값이 아니라 배열과 DAS가 multipath에
|
||||
얼마나 민감한지 비교하는 조건이다. 실제 장치 성능을 평가할 때는 같은 Array/scan/band 설정으로
|
||||
따라서 preset의 RT60이나 wall gain은 특정 방을 인증하는 값이 아니라 배열과 위치 추정 알고리즘이
|
||||
multipath에 얼마나 민감한지 비교하는 조건이다. 실제 장치 성능을 평가할 때는 같은
|
||||
Array/scan/band 설정으로
|
||||
동기식 실측 채널을 [실시간 위치추정 코어](realtime-porting.md)에 입력하고 합성 결과와 나란히
|
||||
비교해야 한다. 주파수 응답 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를 측정했다. 입력은
|
||||
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× |
|
||||
| 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,
|
||||
DAS pass와 readback까지 기다린 시간이다. `end-to-end`에는 이 host 작업과 장치/pipeline 초기화,
|
||||
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.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.comparison-history`: 세션의 배열별 Result 요약을 모은 편의 export. core schema
|
||||
검증 대상은 아니며 각 원본 Result JSON을 대신하지 않는다.
|
||||
@@ -18,17 +18,36 @@ scene JSON에는 192채널 원시 sample이나 원본 asset byte를 넣지 않
|
||||
`sha256` manifest로 참조한다. 사용자 컴퓨터의 절대 경로, URL, `..` 경로는 저장하지 않는다.
|
||||
|
||||
array의 `sensitivityDb`와 `phaseOffsetDeg`는 각 마이크 수신 channel에 적용되는 편차다. 합성기는
|
||||
이를 신호에 주입하고, beamformer는 알려진 calibration 값의 역 gain/phase를 적용한다. 선택적
|
||||
이를 신호에 주입하고, 위치 추정기는 선택한 알고리즘의 규칙에 따라 알려진 calibration을 보정한다.
|
||||
선택적
|
||||
`frequencyResponse`는 2–64개의 `{ frequencyHz, gainDb, phaseDeg? }` 측정점이다.
|
||||
주파수는 0–1,000,000 Hz에서 중복 없이 증가해야 하며, dB와 wrapped phase를 구간 선형 보간하고
|
||||
측정 범위 밖에서는 가까운 끝점을 사용한다.
|
||||
|
||||
Experiment의 선택적 `beamforming.compensateFrequencyResponse`는 기본 `true`다. 합성
|
||||
channel에는 curve가 항상 적용되며, `true`이면 CPU/WebGPU DAS가 선택 bin에서 curve의
|
||||
역 gain/phase도 적용한다. `false`이면 sensitivity/phase calibration은 유지하고 curve
|
||||
역보정만 끈다. 선택적 `beamforming.maxCompensationDb`는 응답 notch의 역보정에서 양의
|
||||
gain boost만 제한하는 0–120 dB 값이며 생략 시 24 dB다. 응답 peak를 줄이는 attenuation과
|
||||
phase 보상은 이 boost 상한을 그대로 적용하지 않는다.
|
||||
Experiment의 필수 `beamforming.algorithm` enum은 `das`, `das-phat`, `gcc-phat`다. backend와
|
||||
raw map 계약은 다음과 같다.
|
||||
|
||||
| algorithm | `rawMap.scale` | 허용 backend |
|
||||
| --- | --- | --- |
|
||||
| `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 재연결
|
||||
|
||||
@@ -80,24 +99,55 @@ room 안의 min/max, 고유 id, -120–0 dB의 `transmissionDb`와
|
||||
gain을 보존하고, `peak`는 합성 전 peak를 `targetPeak`에 맞춘다. result의 `signalStats`에는
|
||||
정규화 전 peak, 실제 scale, scale 적용 후에도 범위를 넘은 sample 수를 기록한다.
|
||||
|
||||
이는 acoustic map 표시 정규화와 별개다. result의 `rawMap`은 반드시 선형 power이고,
|
||||
`displayMap`은 peak-normalized 값 또는 dB 값일 수 있다. 후처리 결과는 `processedMaps`에 넣어
|
||||
raw DAS map을 덮어쓰지 않는다.
|
||||
이는 acoustic map 표시 정규화와 별개다. result의 `rawMap.scale`은 알고리즘의 원래 비음수 map을
|
||||
뜻하는 `power` 또는 `score`다. DAS의 `power`는 절대 SPL로 calibration한 값이 아니며,
|
||||
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`
|
||||
방향이다. `values.length`는 반드시 `rows × columns`와 같아야 한다.
|
||||
|
||||
Experiment의 선택적 `evaluation.detectionThresholdRatio`는 최강 local peak power에 대한 검출
|
||||
임계 비율이며 `0 < ratio <= 1`이다. 생략된 이전 문서를 Camera에서 열면 기본값 `0.25`를 적용하며,
|
||||
Experiment JSON을 다시 저장하면 이 값이 명시된다. 값을 낮추면 약한 peak 후보를 포함하지만
|
||||
Experiment의 선택적 `evaluation.detectionThresholdRatio`는 최강 local peak의 같은-scale raw
|
||||
값에 대한 검출 임계 비율이며 `0 < ratio <= 1`이다. 생략된 이전 문서를 Camera에서 열면 기본값
|
||||
`0.25`를 적용하며, Experiment JSON을 다시 저장하면 이 값이 명시된다. 값을 낮추면 약한 peak 후보를 포함하지만
|
||||
sidelobe false positive도 늘 수 있다.
|
||||
|
||||
## Result 평가 정보
|
||||
|
||||
각 band의 `peaks`는 위치와 power 값, 선택적 `sourceId`, `localizationErrorM`,
|
||||
`localizationErrorPixels`, `beamSpread`를 저장한다. `beamSpread`는 선택 peak를 포함하는 연결된
|
||||
half-power 성분의 power 가중 centroid·공분산과 major/minor RMS 반경·각도다. `calibrated`는 현재
|
||||
항상 `false`이며 확률분포, Gaussian 신뢰구간 또는 통계적 위치 불확실성으로 해석하지 않는다.
|
||||
새 Result는 최상위 `algorithm`에 실제 실행한 `das`, `das-phat` 또는 `gcc-phat`를 기록하며
|
||||
Experiment의 선택값과 같아야 한다. 이 필드는 이전 `1.0.0` Result를 읽기 위해 schema상 선택적으로
|
||||
남아 있지만 현재 export에는 항상 들어간다. `backend`는 요청값 `auto`가 아니라 실제 사용한
|
||||
`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`에는 다음 유한값만 기록한다.
|
||||
|
||||
- `peakToSidelobeDb`
|
||||
@@ -105,6 +155,9 @@ half-power 성분의 power 가중 centroid·공분산과 major/minor RMS 반경
|
||||
- `precision`, `recall`
|
||||
- `mainLobeWidthM`
|
||||
|
||||
호환 필드명 `energyInsideTruthRatio`는 `power` map에서는 truth 주변 power 비율, `score` map에서는
|
||||
truth 주변 score 비율이다. 후자의 값은 물리적 energy 비율이나 위치 확률이 아니다.
|
||||
|
||||
`evaluation`은 지표를 다시 해석할 수 있도록 truth 반경, source 매칭 tolerance, peak 검출
|
||||
threshold와 최소 거리, sidelobe 제외 반경, half-power 비율, dynamic range, 최대 검출 수를
|
||||
버전과 함께 저장한다. `environment`에는 실제 backend, microphone/grid 수, scan bounds와 z,
|
||||
@@ -146,7 +199,8 @@ CPU 분석 계획은 기본 512 MiB, 반복 steering cache는 64 MiB, streaming
|
||||
256 MiB hard cap을 할당 전에 적용한다. 채널 순서와 streaming 상태 계약은
|
||||
[실측 다채널 위치추정 코어 포팅](realtime-porting.md)을 참고한다.
|
||||
|
||||
portable block 결과의 `processingTimeMs`는 DAS와 local-peak 검출 wall time이다. Streaming
|
||||
portable block 결과의 `processingTimeMs`는 선택한 위치 추정 알고리즘과 local-peak 검출 wall
|
||||
time이다. Streaming
|
||||
결과는 `deadlineMs`와 `deadlineMet`을 추가하고 상태에는 최근·최대 처리 시간,
|
||||
`deadlineMisses`와 `droppedSamples`를 누적한다. 이 runtime telemetry는
|
||||
`micarrsim.result` 저장 스키마의 필수 필드가 아니다.
|
||||
|
||||
+24
-18
@@ -2,8 +2,8 @@
|
||||
|
||||
> 구현 상태 · 2026-08-28
|
||||
>
|
||||
> 단계 0–4와 단계 5의 저비용 음향 환경·마이크 응답·portable streaming core까지 완료했다.
|
||||
> 설치 없는 브라우저 앱, CPU/WebGPU DAS, Builder→Camera asset 재연결, 임의 오디오·이동
|
||||
> 단계 0–4와 단계 5의 저비용 음향 환경·마이크 응답·다중 알고리즘 portable streaming core까지 완료했다.
|
||||
> 설치 없는 브라우저 앱, CPU/WebGPU DAS·DAS-PHAT와 CPU GCC-PHAT, Builder→Camera asset 재연결, 임의 오디오·이동
|
||||
> trajectory, 빔 분포·복수 peak 감도, 라이브 시간축 재생, 배열 비교와 Result 내보내기를
|
||||
> 전체 자동 테스트로 검증했다. 실제 장치 adapter와 현장 검증은 장치 계약이 필요한 후속 범위다.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
1. 기계음 데이터와 ambient audio를 조합해 장면 및 ground truth를 생성한다.
|
||||
2. 배열 JSON과 장면 정보를 사용해 각 마이크에 도달하는 신호를 합성한다.
|
||||
3. WGSL로 conventional delay-and-sum(DAS) 빔포밍을 수행한다.
|
||||
3. DAS, DAS-PHAT 또는 GCC-PHAT로 위치 map을 계산하고 같은 입력에서 비교한다.
|
||||
4. 주파수 구간별 acoustic image를 ground truth 위에 표시하고 정량 평가한다.
|
||||
5. 배열, 거리, 음원, 주파수, grid 해상도를 바꾼 실험을 저장하고 비교한다.
|
||||
|
||||
@@ -79,17 +79,21 @@ tap 수가 제한된 RT60 tail만 추가한다. 경로를 source–microphone
|
||||
|
||||
DAS는 STFT 후 각 scan point와 마이크 사이 거리로 steering phase를 만들고, 선택된 주파수 bin의
|
||||
정렬 합 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
|
||||
frame·주파수 bin 하나당
|
||||
약 48만 개의 복소 steering 누산이 필요하다. 100×100은 50×50보다 4배, 200×200은 16배이므로
|
||||
장치별 실제 GPU timing을 UI에 표시하고 목표 frame budget에 맞춰 해상도를 제한한다. 정확한 성능과
|
||||
메모리는 대표 GPU에서 benchmark하여 기록하며 이론치만으로 약속하지 않는다.
|
||||
`P` points, `M` microphones, `T__ frames, `F` selected bins에서 DAS 계열 scan은
|
||||
`O(P × M × T × F)`다. GCC-PHAT은 공통 forward STFT 외에 2-pass cross spectrum
|
||||
`2(M-1)TΣF_b`, `(M-1)B` inverse FFT와 `P(M-1)B` lookup을 수행한다.
|
||||
192채널·50×50·46 frames·2 bins의 DAS는 44,160,000 complex MAC이고 같은 한 band
|
||||
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를
|
||||
재사용한다. 192채널·50×50·2 bins를 10회 분석하는 기준에서 거리 계산은 4,800,000회에서
|
||||
실측·반복 분석용 CPU 계획은 거리 행렬과 workspace를 재사용하고, DAS 계열은 bin calibration과
|
||||
허용되는 steering matrix도 재사용한다. 192채널·50×50·2 bins를 10회 DAS 분석하는 기준에서 거리 계산은 4,800,000회에서
|
||||
480,000회, steering pair는 9,600,000회에서 960,000회로 줄어든다. snapshot working set과 계획은
|
||||
512 MiB, steering cache는 64 MiB, streaming input은 256 MiB 기본 hard cap을 할당 전에 적용한다.
|
||||
Streaming ring은 backlog에서 가장 오래된 sample을 버리고 호출당 결과 수를 제한한다.
|
||||
@@ -176,20 +180,21 @@ flattening이 모델 타당성을 훼손하는지 청취 및 spectrum 통계로
|
||||
- peak별 half-power 공분산/RMS 빔 분포와 재현 가능한 검출 임계값
|
||||
- sample-aligned 준정적 시간창 분석, bounded map 계획과 이동 장면 재생
|
||||
|
||||
완료 조건: 사용자가 코드 수정 없이 배열 JSON 두 개를 같은 장면에서 비교할 수 있다.
|
||||
완료 조건: 사용자가 코드 수정 없이 배열 JSON과 위치 추정 알고리즘을 같은 장면에서 비교할 수 있다.
|
||||
|
||||
### 단계 5 — 현실성·포팅과 실제 데이터 · 부분 완료
|
||||
|
||||
- [x] 마이크별 gain·phase·frequency-response 합성 및 선택적 DAS 역보정
|
||||
- [x] 마이크별 gain·phase·frequency-response 합성과 알고리즘별 amplitude/phase 보정
|
||||
- [x] 자유음장을 보존하는 선택형 shoebox 1차 반사·scattering·회절·RT60 tail
|
||||
- [x] Scene 합성에서 분리한 block/streaming multichannel 위치추정 API
|
||||
- [x] 반복 거리·calibration·steering cache, bounded ring과 메모리 hard cap
|
||||
- [x] DAS·DAS-PHAT·reference-pair GCC-PHAT와 알고리즘별 power/score 계약
|
||||
- [ ] 라이선스 검토를 통과한 DCASE/MIMII adapter와 batch workflow
|
||||
- [ ] 실제 장치의 channel/clock/sample 형식에 맞춘 capture·transport adapter와 현장 검증
|
||||
- [ ] 필요 시 센서 self-noise·위치 공차와 DAMAS/CLEAN-SC 후처리
|
||||
|
||||
현재 완료 조건은 기존 자유음장 결과를 유지한 채 propagation model과 응답 보상을 선택해
|
||||
재실행하고, 같은 CPU DAS를 실측 `Float32Array` channel에 직접 적용하는 것이다. 실제
|
||||
재실행하고, 선택한 CPU 위치 추정기를 실측 `Float32Array` channel에 직접 적용하는 것이다. 실제
|
||||
hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정한다.
|
||||
|
||||
## 9. 주요 위험과 대응
|
||||
@@ -203,7 +208,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
||||
쓴다. 실제 데이터 adapter는 단계 5의 라이선스 검토 뒤 추가한다.
|
||||
- 실제 AC와 simulation gap: gain·phase·주파수 응답과 희소 실내 환경을 비교 조건으로 제공하되,
|
||||
위치 공차·self-noise·ADC·clock은 실측 adapter와 현장 검증으로 다룬다.
|
||||
- post-processing이 기본 결과를 가림: raw DAS map과 후처리 map을 항상 별도로 보존한다.
|
||||
- post-processing이 기본 결과를 가림: 알고리즘별 raw power/score map과 후처리 map을 별도로 보존한다.
|
||||
|
||||
## 10. 구현 결과와 다음 백로그
|
||||
|
||||
@@ -211,6 +216,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
||||
- [x] array/scene/experiment/result schema와 synthetic fixture
|
||||
- [x] 좌표·거리·구면 감쇠·분수 지연·STFT 단위 테스트
|
||||
- [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] scene canvas, array view, parameter controls와 Result export
|
||||
- [x] Builder→Camera SHA-256 asset 재연결 왕복 테스트
|
||||
@@ -220,7 +226,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
||||
- [x] 복수 음원용 Experiment peak 검출 감도
|
||||
- [x] 마이크 주파수 응답 합성·CPU/WebGPU 역보정 비교
|
||||
- [x] 자유음장·shoebox 희소 반사/산란/회절/RT60 환경 선택
|
||||
- [x] portable block/streaming localizer와 반복 DAS cache·메모리 상한
|
||||
- [x] portable block/streaming localizer와 알고리즘별 반복 plan·메모리 상한
|
||||
- [x] Camera 입력→설정→실행→확인의 Snapshot/Moving UI 재구성
|
||||
- [x] `test.cmd` one-command headless browser 검증
|
||||
- [ ] DCASE/MIMII 라이선스 검토와 adapter
|
||||
@@ -229,5 +235,5 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
|
||||
- [ ] DAMAS/CLEAN-SC 후처리
|
||||
|
||||
정확성 test를 먼저 통과시킨 뒤 UI 또는 최적화를 진행한다는 원칙은 유지한다. 추가 현실성 모델은
|
||||
자유음장 DAS 결과를 바꾸지 않는 선택형 확장으로, 장치 연결은 portable localizer 앞의 adapter로
|
||||
자유음장 DAS 기준 결과를 바꾸지 않는 선택형 확장으로, 장치 연결은 portable localizer 앞의 adapter로
|
||||
추가한다.
|
||||
|
||||
+59
-24
@@ -112,26 +112,48 @@
|
||||
<section class="guide-section">
|
||||
<div class="section-number">04</div>
|
||||
<div>
|
||||
<p class="eyebrow">Compute backend</p>
|
||||
<h2>속도와 격자 선택</h2>
|
||||
<p class="eyebrow">Localization & compute</p>
|
||||
<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">
|
||||
<table>
|
||||
<thead><tr><th>선택</th><th>동작</th><th>권장 상황</th></tr></thead>
|
||||
<tbody>
|
||||
<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>CPU 강제</td><td>동일한 conventional DAS를 CPU에서 계산</td><td>호환성 확인·기준 비교</td></tr>
|
||||
<tr><td>WebGPU 강제</td><td>DAS/DAS-PHAT를 GPU에서만 실행; 실패하면 fallback 없이 오류</td><td>GPU 비교·측정</td></tr>
|
||||
<tr><td>CPU 강제</td><td>선택한 알고리즘을 CPU에서 계산</td><td>호환성 확인·기준 비교</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<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 class="guide-copy">
|
||||
복수 음원에서 약한 peak가 빠지면 <strong>Peak 검출 임계값</strong>을 기본 25%에서
|
||||
10–20%로 낮춰 보세요. 약한 후보와 함께 sidelobe 오검출도 늘 수 있으며, main lobe보다
|
||||
가까운 같은 대역 음원은 conventional DAS에서 하나로 합쳐질 수 있습니다.
|
||||
먼저 50×50을 권장합니다. 100×100은 4배, 200×200은 16배의 scan point를 계산합니다.
|
||||
연산량 줄은 공통 STFT transform과 함께 DAS/DAS-PHAT의 complex MAC, 또는 GCC-PHAT의
|
||||
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>
|
||||
</div>
|
||||
</section>
|
||||
@@ -144,11 +166,12 @@
|
||||
<p class="guide-copy">
|
||||
고급 설정에서 자유음장 또는 흡음·일반·반사 강한 실내 preset을 고릅니다. 실내 모델은
|
||||
1차 반사, scattering, occluder 회절과 제한된 RT60 tail을 희소 경로로 근사합니다.
|
||||
Array의 마이크 응답 curve는 수신 신호에 적용하며 DAS 역보정 유무를 비교할 수 있습니다.
|
||||
Array의 마이크 응답 curve는 수신 신호에 적용하며 위치추정 역보정 유무를 비교할 수 있습니다.
|
||||
값과 한계는 <a href="/docs/acoustic-model.md">음향 모델 설명</a>에서 확인하세요.
|
||||
</p>
|
||||
<p class="guide-copy">
|
||||
실제 동기식 마이크 채널은 Scene 합성 없이 portable CPU DAS에 넣을 수 있습니다.
|
||||
실제 동기식 마이크 채널은 Scene 합성 없이 portable CPU 위치추정 코어에 넣고
|
||||
DAS·DAS-PHAT·GCC-PHAT를 선택할 수 있습니다.
|
||||
장치별 channel·clock·transport adapter는 별도로 필요하며 실시간 deadline은 해당
|
||||
장치에서 <code>processingTimeMs ≤ deadlineMs</code>와 miss·drop 누계로 확인해야
|
||||
합니다. <a href="/docs/realtime-porting.md">포팅 설명서</a>에 입력 형식, ring buffer,
|
||||
@@ -163,19 +186,26 @@
|
||||
<p class="eyebrow">Result JSON</p>
|
||||
<h2>무엇이 저장되나요?</h2>
|
||||
<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>beamSpread</dt><dd>half-power lobe의 power 가중 공분산과 1× RMS ellipse</dd></div>
|
||||
<div><dt>metrics</dt><dd>energy 비율, precision/recall, sidelobe, main-lobe 폭</dd></div>
|
||||
<div><dt>beamSpread</dt><dd>half-power 또는 half-maximum 응답의 map 값 가중 공분산과 1× RMS ellipse</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>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>comparison-history</dt><dd>세션의 배열별 시간·위치 오차·PSR 요약을 한 번에 저장</dd></div>
|
||||
<div><dt>comparison-history</dt><dd>배열·알고리즘·실제 backend별 시간·위치 오차·PSR 요약</dd></div>
|
||||
</dl>
|
||||
<aside class="callout">
|
||||
화면의 <strong>빔 분포</strong> 1×/2× RMS contour는 acoustic power lobe의 모양입니다.
|
||||
위치 확률, Gaussian 신뢰구간 또는 보정된 측정 불확실성이 아닙니다.
|
||||
DAS map은 acoustic power 응답이고 PHAT map은 무차원 위치추정 score입니다. score와
|
||||
화면의 <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 class="callout">
|
||||
평가는 tone 음원을 해당 주파수 대역이 tone 주파수를 포함할 때만 정답으로 사용합니다.
|
||||
@@ -183,7 +213,7 @@
|
||||
에너지를 자동 판정하는 기능은 아직 없습니다.
|
||||
</aside>
|
||||
<p class="guide-copy">
|
||||
Camera에서 바꾼 Scene과 Experiment는 각각 저장할 수 있습니다. 완료 Result와 배열 비교
|
||||
Camera에서 바꾼 Scene과 Experiment는 각각 저장할 수 있습니다. 완료 Result와 비교
|
||||
기록도 별도 JSON으로 저장하세요. 저장하지 않은 항목이나 실행 중인 계산이 있으면
|
||||
페이지를 닫을 때 브라우저가 확인합니다.
|
||||
</p>
|
||||
@@ -213,7 +243,11 @@
|
||||
</details>
|
||||
<details>
|
||||
<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>
|
||||
<summary>두 번째 음원을 찾지 못합니다.</summary>
|
||||
@@ -233,10 +267,11 @@
|
||||
<h2>현재 모델의 범위</h2>
|
||||
<p class="guide-copy">
|
||||
micarrsim 1.0은 점 음원의 자유음장과 계산량을 제한한 shoebox 희소 경로, 마이크
|
||||
주파수 응답과 conventional DAS를 제공합니다. 파동 방정식·고차 반사·재질별 흡음,
|
||||
복잡한 mesh, sensor self-noise·비선형, ADC·clock, DAMAS/CLEAN-SC와 자동 장치
|
||||
capture adapter는 포함하지 않습니다. 결과는 장비의 절대 성능 보증이 아니라 같은
|
||||
조건에서 배열과 알고리즘을 비교하는 재현 가능한 기준입니다.
|
||||
주파수 응답과 DAS·DAS-PHAT·GCC-PHAT를 제공합니다. 파동 방정식·고차 반사·재질별
|
||||
흡음, 복잡한 mesh, sensor self-noise·비선형, ADC·clock, DAMAS/CLEAN-SC 후처리와
|
||||
자동 장치 capture adapter는 포함하지 않습니다. 실행할 수 없는 DAMAS/CLEAN-SC
|
||||
placeholder는 Camera UI에서 제거했습니다. 결과는 장비의 절대 성능 보증이 아니라
|
||||
같은 조건에서 배열과 알고리즘을 비교하는 재현 가능한 기준입니다.
|
||||
</p>
|
||||
<p class="guide-copy">
|
||||
원본 asset은 브라우저 메모리에서만 읽고 서버나 외부 네트워크로 보내지 않습니다.
|
||||
|
||||
+175
-35
@@ -1,7 +1,7 @@
|
||||
# 실측 다채널 위치추정 코어 포팅
|
||||
|
||||
`packages/acoustics-core/realtime-localizer.js`는 Scene 생성이나 음향 합성 없이 이미 sampling된
|
||||
동기식 마이크 채널을 conventional CPU DAS에 직접 넣는다. 브라우저 DOM과 외부 package에
|
||||
동기식 마이크 채널을 CPU DAS·DAS-PHAT·GCC-PHAT 위치 추정에 직접 넣는다. 브라우저 DOM과 외부 package에
|
||||
의존하지 않는 ES module이므로, 실제 장치 adapter 뒤에 붙이거나 다른 프로젝트로 분리할 수 있다.
|
||||
|
||||
이 API는 ADC와 transport를 제어하지 않는다. 입력 channel을 획득·정렬·동기화한 다음 위치 map과
|
||||
@@ -9,13 +9,16 @@
|
||||
|
||||
## 최소 복사 단위
|
||||
|
||||
직접 경로로 `realtime-localizer.js`를 import한다면 다음 여덟 파일과 상대 경로를 함께
|
||||
직접 경로로 `realtime-localizer.js`를 import한다면 다음 열한 파일과 상대 경로를 함께
|
||||
복사하면 된다.
|
||||
|
||||
```text
|
||||
acoustics-core/
|
||||
realtime-localizer.js
|
||||
localization.js
|
||||
localization-algorithms.js
|
||||
das.js
|
||||
gcc-phat.js
|
||||
stft.js
|
||||
fft.js
|
||||
math.js
|
||||
@@ -24,8 +27,10 @@ acoustics-core/
|
||||
evaluation.js
|
||||
```
|
||||
|
||||
`index.js`는 전체 core의 편의 export이므로 최소 포팅에는 필요하지 않다. 현재 portable API는
|
||||
CPU 기준 구현이며 Camera의 WebGPU worker나 Scene·propagation 모듈을 요구하지 않는다.
|
||||
`index.js`는 전체 core의 편의 export이므로 최소 포팅에는 필요하지 않다. Portable API와
|
||||
`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다.
|
||||
응답 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 설정이 바뀌지 않는 동안 계획을 한 번 만들고 재사용한다.
|
||||
@@ -94,6 +151,7 @@ const plan = createLocalizationPlan({
|
||||
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
||||
],
|
||||
stft: { fftSize: 512, hopSize: 256 },
|
||||
algorithm: "das", // "das" | "das-phat" | "gcc-phat"
|
||||
speedOfSound: 343,
|
||||
normalization: "peak",
|
||||
compensateFrequencyResponse: true,
|
||||
@@ -113,19 +171,63 @@ const plan = createLocalizationPlan({
|
||||
- scan의 `columns`와 `rows`는 양의 정수
|
||||
- `speedOfSound`는 양수
|
||||
- `normalization`은 `peak` 또는 `none`
|
||||
- `algorithm`은 `das`, `das-phat`, `gcc-phat` 중 하나
|
||||
- `phatRelativeFloor`와 `phatFloorRatio`는 지정한 경우 0–1
|
||||
- `maxCompensationDb`는 0–120 dB
|
||||
- `peakDetection.thresholdRatio`는 0–1,
|
||||
`minimumPeakDistanceM`는 0 이상,
|
||||
`maximumDetections`는 1–128의 정수
|
||||
|
||||
계획은 거리 행렬, bin calibration, 임시 map과 허용되는 경우 steering matrix를 유지하는
|
||||
stateful 객체다. 같은 계획으로 두 분석을 동시에 실행하지 말고, worker마다 별도 계획을 만든다.
|
||||
Array·scan·band·STFT를 바꾸면 새 계획을 만들어야 한다.
|
||||
계획은 알고리즘별 거리 행렬과 workspace를 유지하는 stateful 객체다. DAS 계열은 bin calibration,
|
||||
임시 map과 허용되는 경우 steering matrix를 유지하고, GCC-PHAT는 reference mic 선택,
|
||||
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
|
||||
loop에 양보한다. `computeOptions.pointBatchSize`와
|
||||
`computeOptions.stftTransformBatchSize`로 조정할 수 있지만, 큰 batch는 throughput과
|
||||
취소·UI 응답성의 trade-off가 있으므로 장치에서 함께 측정한다.
|
||||
portable 계획의 기본 scan point batch는 DAS 계열 256개, GCC-PHAT 4,096개이고 STFT transform
|
||||
batch는 128개다. GCC-PHAT cross-spectrum은 16,384 operation 단위로도 양보한다. 각 batch 경계에서
|
||||
event loop에 기회를 주며 `computeOptions.pointBatchSize`,
|
||||
`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) {
|
||||
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
|
||||
안에서는 power가 강한 순서이며 항목에는 `bandId`, band 내 `rank`, scan
|
||||
`index`, `position`과 `rawPower`가 있다. 기본 threshold는 해당 band 최강
|
||||
peak의 50%, 최소 peak 간격은 scan cell 대각선, 최대 검출 수는 band당 8개다. 여러 대역을
|
||||
사용한다면 `bandId`로 묶어 해석한다.
|
||||
안에서는 `rawValue`가 큰 순서이며 항목에는 `bandId`, band 내 `rank`, scan `index`,
|
||||
`position`, `rawValue`, `rawScale`이 있다. DAS의 기존 `rawPower` 필드는 호환 alias로 유지된다.
|
||||
Score 결과에서는 `rawValue`를 공통 필드로 읽고, `rawScore`가 포함된 peak 객체에서는 같은 값의
|
||||
score alias로 사용할 수 있다. 기본 threshold는 해당 band 최강 peak의 50%, 최소 peak 간격은
|
||||
scan cell 대각선, 최대 검출 수는 band당 8개다. 여러 대역을 사용한다면 `bandId`로 묶어 해석한다.
|
||||
|
||||
`peakDetection`은 후처리 위치 목록만 바꾸며 `result.bands[n].rawMap`과
|
||||
`displayMap`은 그대로 보존한다. 같은 대역의 두 음원이 main lobe보다 가까우면 local
|
||||
peak가 하나로 합쳐질 수 있고, threshold를 낮추면 sidelobe 후보도 늘 수 있다.
|
||||
`sampleCount`와 `duration`도 결과에 함께 반환된다.
|
||||
|
||||
Block 결과의 `processingTimeMs`는 DAS 계산과 local-peak 검출에 걸린 monotonic wall
|
||||
Block 결과의 `processingTimeMs`는 선택한 위치 추정 계산과 local-peak 검출에 걸린 monotonic wall
|
||||
time이다. capture, adapter 변환과 결과 rendering 시간은 포함하지 않으므로 end-to-end latency는
|
||||
호출자가 별도로 측정한다.
|
||||
|
||||
@@ -168,13 +276,14 @@ time이다. capture, adapter 변환과 결과 rendering 시간은 포함하지
|
||||
|
||||
## 연속 chunk 처리
|
||||
|
||||
`StreamingDasLocalizer` 또는 같은 factory인 `createStreamingLocalizer`는 고정 용량
|
||||
ring buffer와 분석 workspace를 갖는다.
|
||||
`StreamingLocalizer`는 알고리즘 중립 이름이며 기존 `StreamingDasLocalizer` class의 export alias다.
|
||||
오래된 이름은 호환을 위해 유지된다. 두 이름과 `createStreamingLocalizer` factory는 모두 선택한
|
||||
`algorithm`에 맞는 고정 용량 ring buffer와 분석 workspace를 만든다.
|
||||
|
||||
```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,
|
||||
array,
|
||||
scan: {
|
||||
@@ -190,6 +299,8 @@ const localizer = createStreamingLocalizer({
|
||||
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
|
||||
],
|
||||
stft: { fftSize: 512, hopSize: 256 },
|
||||
algorithm: "das-phat",
|
||||
phatRelativeFloor: 1e-6,
|
||||
analysisWindowSamples: 4_800,
|
||||
analysisHopSamples: 2_400,
|
||||
maximumBufferedSamples: 19_200,
|
||||
@@ -224,6 +335,11 @@ async function analysisLoop(signal) {
|
||||
`deadlineMs = analysisHopSamples / sampleRate × 1000`과
|
||||
`deadlineMet = processingTimeMs <= deadlineMs`를 반환한다.
|
||||
|
||||
`deadlineMet`는 완료된 한 창의 위치 추정 시간이 hop 예산 안이었는지를 나타내는 측정값이지,
|
||||
해당 구성이 실시간이라는 사전 보장이 아니다. JIT warm-up, GC, 다른 thread의 부하를 포함해 목표
|
||||
장치에서 연속 실행을 측정해야 한다. 이 값은 capture·transport·rendering을 포함하지 않으므로 전체
|
||||
시스템 deadline은 adapter 경계에서 따로 계측한다.
|
||||
|
||||
## 지연과 backpressure 조정
|
||||
|
||||
서로 다른 hop이 두 층에 있다.
|
||||
@@ -268,18 +384,42 @@ async function analysisLoop(signal) {
|
||||
|
||||
입력 retained byte는
|
||||
`채널 수 × (maximumBufferedSamples + analysisWindowSamples) × 4`이며 할당 전에 검사한다.
|
||||
계획은 거리 행렬, bin calibration, Hann window, Float64 FFT workspace와 임시 map을 재사용한다.
|
||||
기본 retained data가 `maximumPlanBytes`를 넘으면 계획 생성을 거절한다. 전체 steering
|
||||
matrix가 64 MiB 또는 계획 전체 한도를 넘으면 선택 bin 앞쪽부터 예산에 들어가는 만큼만 cache하고
|
||||
나머지는 고정 microphone workspace에서 필요할 때 계산한다.
|
||||
모든 계획은 거리 행렬과 STFT workspace를 재사용한다. DAS 계열은 bin calibration, Hann window,
|
||||
임시 map과 steering cache를, GCC-PHAT는 선택 bin metadata, reference mic와 correlation workspace를
|
||||
재사용한다. 기본 retained data가 `maximumPlanBytes`를 넘으면 할당 전에 계획 생성을 거절한다.
|
||||
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회로
|
||||
줄어든다. 17,280,000회의 `sin/cos` 호출을 피하고 약 16.5 MiB를 유지한다. 자동 테스트는
|
||||
부분 cache와 cache 없음의 raw/display `Float32` map 모든 원소가 bit-exact임을 확인한다.
|
||||
각 결과의 `analysisCache`에는 cache된 bin capacity와 실제 cached/uncached 사용,
|
||||
거리·steering pair, STFT transform·FFT butterfly·DAS complex MAC, workspace allocation·reuse
|
||||
수가 들어가므로 설정별 최적화 효과를 계측할 수 있다.
|
||||
각 결과의 `analysisCache`에는 공통 거리·STFT 통계와 알고리즘별 작업량이 들어간다. DAS 계열은
|
||||
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로 전달한다.
|
||||
|
||||
캐시 최적화와 위 수치는 반복 계산 감소의 근거이지 192채널·50×50 또는 다른 구성이 실시간이라는
|
||||
보장이 아니다. 마이크 수, scan point, 선택 bin, STFT frame에 따른 주연산은 여전히 대략
|
||||
`O(P × M × F × T)`다. `deadlineMisses` 또는 `droppedSamples`가 누적되면
|
||||
grid·band bin·FFT/분석창 또는 update rate를 줄여야 한다. deadline은 위치추정 처리량 판정이며
|
||||
capture와 출력까지 포함하는 시스템 deadline은 adapter에서 별도로 검증한다.
|
||||
보장이 아니다. `deadlineMisses` 또는 `droppedSamples`가 누적되면 grid·band bin·FFT/분석창 또는
|
||||
update rate를 줄여야 한다. 평균 한 번만 재지 말고 목표 장치의 실제 입력으로 warm-up 뒤 충분히 긴
|
||||
구간의 최대값과 상위 percentile을 측정한다. Capture와 출력까지 포함하는 시스템 deadline은
|
||||
adapter에서 별도로 검증한다.
|
||||
|
||||
## 취소와 오류 복구
|
||||
|
||||
`localizeMultichannel`과 `analyzeAvailable`에 `AbortSignal`을 전달하면 STFT와
|
||||
DAS batch 경계에서 `AbortError`를 발생시키고 계획 lock을 해제한다.
|
||||
알고리즘별 scan/correlation batch 경계에서 `AbortError`를 발생시키고 계획 lock을 해제한다.
|
||||
|
||||
Streaming 분석이 취소되거나 실패하면 `failedAnalyses`가 증가하지만 해당 hop을
|
||||
소비하지 않는다. 실패한 창은 별도 analysis workspace에 보존되며, 다음
|
||||
@@ -329,4 +469,4 @@ hop을 commit하고 sequence를 증가시킨다.
|
||||
|
||||
코어 뒤에서는 `locations`를 제어에 바로 쓰기 전에 현장 데이터로 검출 임계값, false peak,
|
||||
latency와 위치 오차를 검증해야 한다. 현재 `locations`는 통계적 신뢰구간이 아니라 각 band
|
||||
DAS map에서 threshold와 거리 억제를 통과한 grid local peak 후보들이다.
|
||||
위치 map에서 threshold와 거리 억제를 통과한 grid local peak 후보들이다.
|
||||
|
||||
Reference in New Issue
Block a user