feat: add physically explicit narrowband MUSIC

This commit is contained in:
2026-08-29 12:40:48 +09:00
parent 044be3cf92
commit 11fee76280
40 changed files with 6473 additions and 275 deletions
+61 -8
View File
@@ -227,6 +227,54 @@ band는 주기적으로 같은 phase를 만드는 lag가 많아 여러 위치가
해결하지는 않는다. 단일 reference 방식은 모든 마이크 쌍을 쓰는 GCC보다 계산량이 작지만 pair
중복성과 고장 마이크에 대한 강건성도 작다.
### Narrowband MUSIC (`music`)
현재 CPU MUSIC은 [Schmidt의 noise-subspace 방법](https://doi.org/10.1109/TAP.1986.1143830)을
근거리 구면파 direct-path manifold에 적용한다. 근거리 source localization의 관련 문헌은
[Huang–Barkat](https://doi.org/10.1109/8.86917)이다. 보정된 snapshot
`x(t)`로 mean subtraction 없는 sample covariance를 만든다.
```text
R = (1/T) Σ_t x(t) x(t)ᴴ
R v_j = λ_j v_j, λ_0 ≥ ... ≥ λ_(M-1)
q(p) = Σ_(j=K)^(M-1) |v_jᴴ a(p)|² / (a(p)ᴴ a(p))
```
`q`는 noise projection fraction이고 optimum은 minimum이다. UI/evaluation은 표준
pseudospectrum `P=1/q`를 scan 안에서 `P/Pmax`로 표시한다. `q_min>0`이면 이는
`q_min/q(p)`이고, `q_min=0`이면 정확한 zero 위치만 1로 표시한다. flat `q`는 모두 1로
표시하되 위치 peak는 만들지 않는다. `q`, `P`와 `P/Pmax`는 확률·posterior·confidence 또는
신뢰구간이 아니다.
Experiment band는 `Fs/N` grid에 놓인 아날로그 carrier 가설을 정확히 하나만 포함한다.
`f_a`를 그 center, signed ADC alias의 orientation을 `η = sign(f_s)`라 하면 공간 위상의
크기는 analog carrier `f_a`를 유지하고 `η`만 alias inversion 방향으로 사용한다.
```text
a_m(p) = H_m,residual(f_a) / max(r_m(p), d_min)
× exp[-j η 2π f_a (r_m(p)-r_0(p))/c + j φ_m,residual(f_a)]
```
`f_s<0`인 alias inversion에서는 positive-bin STFT coefficient, sensitivity/response 보정과
전체 complex manifold가 baseband 가설의 켤레 방향이 된다. microphone frequency response는
관측 bin이 아니라 사용자가 지정한 `f_a`에서 평가한다. 이 가설은 Experiment에서 오며 Scene
source frequency·position truth는 covariance, K 선택이나 scan에 사용하지 않는다. 같은 ADC
bin의 다른 alias order는 별도 band로 명시해야 하고 자동 선택하지 않는다. 정확한 DC와 Nyquist는
실수 sequence에 독립 quadrature가 없어 거부한다.
K는 사용자가 고정하거나 [Wax–Kailath AIC/MDL](https://doi.org/10.1109/TASSP.1985.1164557)로
선택한다. AIC/MDL은 비중첩 complete snapshot, `T>M`, roundoff보다 엄격히 큰 noise eigenvalue가
필요하고 IID complex Gaussian snapshot, spatially white noise, 창 동안 일정한 source 수를
가정한다. 비중첩 자체는 통계적 독립성의 증명이 아니며 criterion은 확률이나 confidence가 아니다.
가정/수치 조건이 깨지면 typed `MUSIC_UNAVAILABLE` 오류를 내고 fixed K로 fallback하지 않는다.
같은 주파수의 coherent source는 signal covariance rank를 잃을 수 있다. eigengap이 수치 audit
bound보다 작으면 subspace를 임의 분할하지 않는다. diagonal loading, eigenvalue floor, spatial
smoothing, band 간 association·평균·maximum fusion은 없다. 배열의 spatial alias/grating lobe,
동률과 flat objective도 결과를 좋게 보이도록 제거하지 않는다.
[Wax–Shan–Kailath broadband eigenstructure 방법](https://doi.org/10.1109/TASSP.1984.1164400)은
알려진 별도 알고리즘이지만 현재 구현하지 않았다.
## 샘플링, Nyquist와 alias
Scene의 `sampleRate`는 모든 마이크가 동시에 동작하는 이상적 real-valued ADC의 sampling rate다.
@@ -269,16 +317,19 @@ alias-equivalent band ID를 보존한다. 같은 `adcBinSetKey`를 가진 band
`-Fs/2` endpoint는 두 관측이나 두 FFT bin이 아니라 같은 phase-degenerate Nyquist
sample을 양쪽 zone에서 표현한 것이다.
같은 이유로 위치 추정기의 선택적 microphone-response 역보정도 관측 ADC bin에서 평가한다. Forward
tone 합성은 원 analog 주파수의 응답을 사용하므로, Nyquist 위 carrier를 알고 보정하는 별도
alias-aware 알고리즘처럼 동작하지 않는다. 이 차이 역시 감추지 않는 현재 알고리즘의 결과다.
같은 이유로 DAS·DAS-PHAT·GCC-PHAT의 선택적 microphone-response 역보정은 관측 ADC bin에서
평가한다. Forward tone 합성은 원 analog 주파수의 응답을 사용하므로 이 세 알고리즘은 Nyquist 위
carrier를 아는 alias-aware 알고리즘처럼 동작하지 않는다. MUSIC만 예외로, 사용자가 band에
명시한 단일 아날로그 FFT-grid 가설에서 response와 signed complex manifold를 계산한다. 이는
Scene truth를 읽거나 가능한 alias order를 자동 탐색하는 것이 아니다.
서로 다른 analog tone이 같은 ADC bin으로 접히면 **단일 channel의 시간 sample만으로는**
원 주파수를 구별할 수 없다. 그러나 이 합성기는 원 analog 파장의 센서 간 위상을 보존하므로,
충분히 촘촘하고 보정된 다채널 array에는 carrier order를 판별할 공간 위상 증거가 남을 수 있다.
현재 DAS·DAS-PHAT·GCC-PHAT는 carrier hypothesis를 열거하는 알고리즘이 아니므로 이를 복원하지
않고 Result에 `aliasOrderResolution: not-attempted`로 기록한다. 이 기능을 추가하려면 검증된
array-processing 방법과 별도 alias-order 평가가 필요하며, 임의 규칙으로 peak를 고르지 않는다.
않고 Result에 `aliasOrderResolution: not-attempted`로 기록한다. MUSIC은 band 하나에 사용자가
고른 가설 하나만 계산해 `configured-single-hypothesis`로 기록하며, 후보 중 승자를 고르지 않는다.
여러 order를 비교하려면 각각 독립 band로 명시해야 한다.
audio asset과 noise는 이미 sampling된 baseband 신호로 취급하므로 파일에 없는 Nyquist 위 analog
spectrum을 만들어 내지 않는다.
@@ -361,9 +412,11 @@ Result `signalStats`에는 다음 선택 필드가 들어간다.
같은 입력과 seed에서 환경 preset만 바꿨다면 이 값과 위치 오차·precision/recall·PSR을 함께
비교할 수 있다.
Result 최상위 `algorithm`은 실제 실행한 `das`, `das-phat` 또는 `gcc-phat`를 기록한다. band의
`rawMap.scale`은 DAS에서 `power`, 두 PHAT 방식에서 `score`다. peak 정규화된 `displayMap`은
시각 비교용일 뿐 어느 scale도 확률분포나 신뢰구간으로 바꾸지 않는다.
Result 최상위 `algorithm`은 실제 실행한 `das`, `das-phat`, `gcc-phat` 또는 `music`을 기록한다.
band의 `rawMap.scale`은 DAS에서 `power`, 두 PHAT 방식에서 `score`, MUSIC에서
`noise-projection`이다. MUSIC Result는 `musicModel`과 band별 `musicDiagnostics`에 아날로그
가설, alias inversion, covariance/EVD audit와 K 선택 가정을 기록한다. 표시 변환은 어느 scale도
확률분포나 신뢰구간으로 바꾸지 않는다.
## 정확도 범위와 제외 사항
+38 -9
View File
@@ -29,7 +29,7 @@ snap과 zoom은 편집기 상태이며 `micarrsim.array` 계약에 포함되지
`aperture.width/height`와 최종 `microphones` 좌표·순서만 들어간다. 따라서 다른 도구는
형상 이름을 추론하지 않고 실제 좌표를 배열 geometry의 기준으로 사용해야 한다.
Experiment의 필수 `beamforming.algorithm` enum은 `das`, `das-phat`, `gcc-phat`다. backend와
Experiment의 필수 `beamforming.algorithm` enum은 `das`, `das-phat`, `gcc-phat`, `music`이다. backend와
raw map 계약은 다음과 같다.
| algorithm | `rawMap.scale` | 허용 backend |
@@ -37,11 +37,19 @@ raw map 계약은 다음과 같다.
| `das` | `power` | `cpu`, `webgpu`; `auto` 가능 |
| `das-phat` | `score` | `cpu`, `webgpu`; `auto` 가능 |
| `gcc-phat` | `score` | `cpu`; `auto`는 CPU 선택 |
| `music` | `noise-projection` | `cpu`; `auto`는 CPU 선택 |
`gcc-phat`에 명시적 `webgpu`를 조합하면 검증 오류이며, 마이크가 두 개 이상이어야 한다. 필드
그룹 이름 `beamforming`은 기존 계약과의 호환을 위해 유지하지만 세 알고리즘을 모두 선택하는 위치
`gcc-phat` 또는 `music`에 명시적 `webgpu`를 조합하면 검증 오류이며, 마이크가 두 개 이상이어야 한다. 필드
그룹 이름 `beamforming`은 기존 계약과의 호환을 위해 유지하지만 네 알고리즘을 모두 선택하는 위치
추정 설정이다.
MUSIC은 `normalization: "none"`만 허용한다. band마다 analog FFT-grid 가설을 정확히 하나
선택하고, 접힌 양의 ADC bin 하나에서 snapshot covariance를 만든다. Fixed K는 `1..M-1`이다.
Wax–Kailath `mdl`/`aic`는 complete non-overlapping frame, `T > M`, 엄격히 양수인 noise
eigenvalue와 IID complex Gaussian snapshot·spatially white noise·고정 source 수를 가정한다.
non-overlap은 독립성의 증명이 아니다. 조건 불충족은 fixed fallback 없이 typed
`MUSIC_UNAVAILABLE`이다.
선택적 `beamforming.compensateFrequencyResponse`는 기본 `true`다. 합성 channel에는 curve가
항상 적용된다. DAS는 sensitivity와 정적 phase를 항상 역보정하고, 값이 `true`이면 선택 bin에서
curve의 gain과 phase도 역보정한다. DAS-PHAT와 GCC-PHAT는 입력과 calibration의 amplitude gain을
@@ -51,7 +59,8 @@ curve의 gain과 phase도 역보정한다. DAS-PHAT와 GCC-PHAT는 입력과 cal
선택적 `beamforming.maxCompensationDb`는 DAS가 응답 notch를 역보정할 때 양의 gain boost만
제한하는 0–120 dB 값이며 생략 시 24 dB다. 응답 peak를 줄이는 attenuation과 phase 보상은 이
boost 상한의 대상이 아니다. amplitude를 사용하지 않는 DAS-PHAT와 GCC-PHAT에는 이 값이 영향을
주지 않는다. 세 알고리즘의 계산식과 한계는
주지 않는다. MUSIC은 analog 가설에서 residual complex response를 일관되게 manifold에 넣는다.
네 알고리즘의 계산식과 한계는
[음향 환경과 마이크 응답 모델](acoustic-model.md)에 설명한다.
## 로컬 asset 재연결
@@ -127,7 +136,7 @@ sidelobe false positive도 늘 수 있다.
## Result 평가 정보
Result 1.1은 최상위 필수 `algorithm`에 실제 실행한 `das`, `das-phat` 또는 `gcc-phat`를
Result 1.1은 최상위 필수 `algorithm`에 실제 실행한 `das`, `das-phat`, `gcc-phat` 또는 `music`을
기록하며 Experiment의 선택값과 같아야 한다. `backend`는 요청값 `auto`가 아니라 실제 사용한
`cpu` 또는 `webgpu`다.
@@ -180,8 +189,10 @@ threshold와 최소 거리, sidelobe 제외 반경, half-power 비율, dynamic r
경계의 `+Fs/2`와 `-Fs/2`는 같은 실수 sample이며, point provenance는 `+Fs/2`로
canonicalize하고 fold segment endpoint는 zone 진행 방향에 따라 둘 중 하나를 기록한다.
`localizationInputModel`은 one-sided real FFT bin만 사용함을 밝히며, `localizationModel`은
DAS 계열의 구면 steering과 GCC-PHAT의 기하 lag를 구분한다. `originalCarrierUsed`는 항상
`false`다. Nyquist 위 band의 `aliasOrderResolution`은 현재 `not-attempted`다.
DAS 계열의 구면 steering, GCC-PHAT의 기하 lag와 MUSIC의 configured-analog-frequency
near-field manifold를 구분한다. DAS/DAS-PHAT/GCC-PHAT의 `originalCarrierUsed`는 `false`이고
Nyquist 위 band의 `aliasOrderResolution`은 `not-attempted`다. MUSIC의
`originalCarrierUsed: true`는 Scene truth가 아니라 사용자가 지정한 analog 가설을 뜻한다.
`equivalentBandIds`가 있으면 그 band들은 같은 ADC bin 집합을 공유하므로 독립
관측으로 세면 안 된다.
@@ -206,8 +217,26 @@ Array·Scene·Experiment 계약 버전은 `1.0.0`, Result 계약 버전은 `1.1.
`packages/contracts/schema-validator.js`로 저장소의
실제 schema를 실행한 뒤 `validation.js`에서 다음 관계를 추가 검사한다.
Acoustic Camera에서 Experiment를 가져올 때는 문서 자체를 먼저 검증한 뒤 `sceneId`와
`arrayId`를 현재 열린 Scene·Array의 id로 연결하고, 그 context에서 관계 검증을 다시 수행한다.
Acoustic Camera에서 Experiment를 가져올 때는 문서 자체를 먼저 검증한다. `sceneId`와
`arrayId`는 provenance label이므로 현재 열린 Scene·Array ID와 비교해 거부하거나 값을
덮어쓰지 않는다. 실행에는 현재 열린 geometry와 sample data를 사용하고, Result의
`sceneId`/`arrayId`와 `inputHash`에는 실제 사용한 입력을 기록한다.
## MUSIC Result 의미
MUSIC의 `rawMap.scale`은 `noise-projection`이고
`q = ||E_n^H a||²/(a^H a)`의 최솟값이 optimum이다. 표시용 `P/Pmax = q_min/q`도 q와 마찬가지로
확률, likelihood, posterior 또는 신뢰구간이 아니다. `q_min = 0`이면 0인 cell만 1로 표시한다.
Result의 `musicModel`과 band별 `musicDiagnostics`는 source-count 방법·가정,
covariance/eigensolver 감사, analog/ADC alias와 CPU workload를 보존한다.
MUSIC의 `originalCarrierUsed: true`는 Scene truth가 아니라 Experiment에 사용자가 지정한 analog
FFT-grid 가설을 썼다는 뜻이다. analog carrier `f_a`와 관측 alias orientation `η`로
`exp[-j η 2π f_a (r_m-r_ref)/c]`를 만들며, inversion이면 calibration과 steering을 포함한 전체
complex manifold를 켤레화한다. Scene source carrier/위치 truth는 읽지 않는다. 정확한 DC/Nyquist
bin은 quadrature-degenerate라 거절한다. diagonal loading, epsilon/floor, spatial smoothing,
multibin averaging/association과 wideband fusion은 없다. grating lobe, 동률과 coherent-source
rank deficiency는 숨기지 않고 map 또는 typed unavailable로 나타낸다.
이 가져오기 편의 동작은 계약을 완화하지 않는다. 내보내기와 실행에 쓰는 Experiment도 아래 관계를
모두 만족해야 한다.
+6 -1
View File
@@ -206,6 +206,7 @@ flattening이 모델 타당성을 훼손하는지 청취 및 spectrum 통계로
- [x] Scene 합성에서 분리한 block/streaming multichannel 위치추정 API
- [x] 반복 거리·calibration·steering cache, bounded ring과 메모리 hard cap
- [x] DAS·DAS-PHAT·reference-pair GCC-PHAT와 알고리즘별 power/score 계약
- [x] CPU 좁은대역 Schmidt MUSIC, fixed K와 Wax–Kailath AIC/MDL, typed unavailable·연산 상한
- [ ] 라이선스 검토를 통과한 DCASE/MIMII adapter와 batch workflow
- [ ] 실제 장치의 channel/clock/sample 형식에 맞춘 capture·transport adapter와 현장 검증
- [ ] 필요 시 센서 self-noise·위치 공차와 DAMAS/CLEAN-SC 후처리
@@ -227,7 +228,10 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
- 실제 AC와 simulation gap: gain·phase·주파수 응답, ideal real ADC sampling/alias와 희소 실내
환경을 비교 조건으로 제공하되, 위치 공차·self-noise·ADC quantization/nonlinearity와
channel clock jitter/drift는 실측 adapter와 현장 검증으로 다룬다.
- post-processing이 기본 결과를 가림: 알고리즘별 raw power/score map과 후처리 map을 별도로 보존한다.
- post-processing이 기본 결과를 가림: 알고리즘별 raw power/score/noise-projection map과 후처리 map을 별도로 보존한다.
- MUSIC 모호성을 숨김: band당 사용자 지정 analog FFT-grid 가설 하나와 direct-path near-field
manifold만 쓰며 Scene truth, diagonal loading, smoothing, multibin/wideband fusion 없이
grating lobe·동률·coherent rank deficiency를 보존한다.
## 10. 구현 결과와 다음 백로그
@@ -237,6 +241,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
- [x] 좌표·거리·구면 감쇠·분수 지연·STFT 단위 테스트
- [x] CPU DAS golden implementation
- [x] CPU/WebGPU DAS-PHAT와 CPU reference-pair GCC-PHAT 구현·비교 UI
- [x] CPU 좁은대역 MUSIC과 fixed/Wax–Kailath source count, q 최소 목적함수·typed unavailable
- [x] WGSL kernel, CPU/GPU 비교와 50²/100²/200² benchmark
- [x] scene canvas, array view, parameter controls와 Result export
- [x] Builder→Camera SHA-256 asset 재연결 왕복 테스트
+4 -3
View File
@@ -110,8 +110,9 @@
<li>
Camera에서 파일을 <strong>Scene → Array → Experiment → Assets</strong> 순서로
가져오는 것을 권장합니다. Experiment는 어느 시점에 열어도 분석 대역을 보존하고
<code>sceneId</code>와 <code>arrayId</code>를 현재 열린 입력에 자동으로 연결합니다.
재연결 뒤 관계 검증도 다시 수행됩니다. Array Builder에서 저장한 파일이 있다면 Array
<code>sceneId</code>와 <code>arrayId</code> provenance label도 덮어쓰지 않습니다.
실행에는 현재 열린 Scene·Array를 사용하고 Result에 실제 입력 ID와 hash를 기록합니다.
Array Builder에서 저장한 파일이 있다면 Array
단계에서 선택하고, 내 Array/Experiment가 없다면 내장 기본값을 그대로 둡니다.
</li>
<li>
@@ -269,7 +270,7 @@
</details>
<details>
<summary>Experiment를 가져왔는데 검증 오류가 남습니다.</summary>
<p>참조 ID는 현재 Scene·Array에 자동으로 연결됩니다. Nyquist 위 tone·band는 ideal ADC alias로 실행되며 원/관측 주파수가 함께 표시됩니다. 실행할 수 없다면 검증 카드에서 scan 범위, asset처럼 재연결 뒤 확인된 실제 입력 오류를 확인하세요.</p>
<p>참조 ID는 provenance label이라 현재 Scene·Array와 달라도 보존되며 실행을 막지 않습니다. Nyquist 위 tone·band는 ideal ADC alias로 실행되고 원/관측 주파수가 함께 표시됩니다. 실행할 수 없다면 검증 카드에서 scan 범위나 asset처럼 실제 입력 오류를 확인하세요.</p>
</details>
<details>
<summary>Assets가 준비되지 않습니다.</summary>
+34 -3
View File
@@ -83,6 +83,7 @@ Portable plan은 top-level `algorithm`으로 위치 추정기를 선택한다.
| `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 |
| `music` | 표준 좁은대역 Schmidt noise-subspace scan | `noise-projection` | CPU only |
같은 array·scan·band·STFT로 알고리즘을 비교할 때도 알고리즘마다 별도 plan을 만든다.
@@ -103,6 +104,14 @@ const gccPhatPlan = createLocalizationPlan({
algorithm: "gcc-phat",
phatFloorRatio: 1e-6,
});
const musicPlan = createLocalizationPlan({
...commonConfig,
algorithm: "music",
normalization: "none",
musicSourceCountMethod: "fixed",
musicSourceCount: 1,
});
```
`phatRelativeFloor`는 DAS-PHAT의 channel spectrum 정규화 floor이고, `phatFloorRatio`는
@@ -151,7 +160,7 @@ const plan = createLocalizationPlan({
{ id: "machine", minHz: 900, maxHz: 1100, color: "#65f2bf" },
],
stft: { fftSize: 512, hopSize: 256 },
algorithm: "das", // "das" | "das-phat" | "gcc-phat"
algorithm: "das", // "das" | "das-phat" | "gcc-phat" | "music"
speedOfSound: 343,
normalization: "peak",
compensateFrequencyResponse: true,
@@ -174,7 +183,7 @@ const plan = createLocalizationPlan({
- scan의 `columns`와 `rows`는 양의 정수
- `speedOfSound`는 양수
- `normalization`은 `peak` 또는 `none`
- `algorithm`은 `das`, `das-phat`, `gcc-phat` 중 하나
- `algorithm`은 `das`, `das-phat`, `gcc-phat`, `music` 중 하나
- `phatRelativeFloor`와 `phatFloorRatio`는 지정한 경우 0–1
- `maxCompensationDb`는 0–120 dB
- `peakDetection.thresholdRatio`는 0–1,
@@ -186,7 +195,29 @@ const plan = createLocalizationPlan({
STFT·correlation workspace를 유지한다. 같은 계획으로 두 분석을 동시에 실행하지 말고 worker마다
별도 계획을 만든다. Array·scan·band·STFT·알고리즘을 바꾸면 새 계획을 만들어야 한다.
Portable plan의 generic cache는 `plan.analysisPlan`이며 기존 호출자를 위해 DAS 계열에는
`plan.dasPlan`, GCC-PHAT에는 `plan.gccPhatPlan` alias도 제공한다.
`plan.dasPlan`, GCC-PHAT에는 `plan.gccPhatPlan`, MUSIC에는 `plan.musicPlan` alias도 제공한다.
### MUSIC 포팅 경계
MUSIC raw `q = ||E_n^H a||²/(a^H a)`는 작은 값이 좋은 noise projection이다. 표시용
`P/Pmax = q_min/q`도 확률·신뢰도·Gaussian 신뢰구간이 아니며, raw q 보존을 위해
`normalization: "none"`만 허용한다.
band마다 사용자가 지정한 analog FFT-grid 가설 하나와 접힌 positive ADC bin 하나만 사용한다.
Scene carrier/위치 truth는 읽지 않는다. analog carrier `f_a`의 공간 위상을 alias orientation
`η`로 `exp[-j η 2π f_a Δr/c]`에 적용하며, inversion이면 calibration과 steering을 포함한
전체 complex manifold를 켤레화한다. 정확한 DC/Nyquist는 quadrature-degenerate라 거절한다.
Fixed K는 `1..M-1`이다. Wax–Kailath MDL/AIC는 complete non-overlapping frame, `T > M`,
strict-positive noise eigenvalue, IID complex Gaussian snapshot·spatially white noise·고정 K를
가정한다. non-overlap은 독립성의 증명이 아니다. 조건 불충족과 식별 불가능한 partition은
`MusicUnavailableError` (`code: "MUSIC_UNAVAILABLE"`)이며 fixed fallback은 없다.
diagonal loading, floor, spatial smoothing, multibin/wideband fusion도 없다. grating lobe,
동률과 coherent rank deficiency를 결과가 좋아 보이도록 제거하지 않는다.
계획은 allocation 전에 typed working bytes, FFT butterfly, covariance complex accumulation,
Jacobi pair update와 projection MAC 상한을 검사한다. 이 CPU cap은 메모리·응답성 보호 장치이지
realtime 보장이 아니므로 `processingTimeMs`와 streaming deadline 통계를 대상 장치에서 측정한다.
portable 계획의 기본 scan point batch는 DAS 계열 256개, GCC-PHAT 4,096개이고 STFT transform
batch는 128개다. GCC-PHAT cross-spectrum은 16,384 operation 단위로도 양보한다. 각 batch 경계에서