# Whisper Audio Pipeline -- Design Notes

> WhisperEngine의 음향 처리 파이프라인 설계.
> 속삭임 인식을 위한 다단계 노이즈 필터링 + 음원 분리 + 발음 코드화 + 멀티플레이어 확장.

---

## 1. 3단계 노이즈 필터링

### Stage 1: Energy Gate (녹음 단계 문지기)

프레임 에너지가 허용 범위 밖이면 통째로 버린다.

| 판정 | 조건 | 처리 |
|------|------|------|
| **QUIET** | `maxEnergy < 0.001` | 침묵 -- 녹음 제외 |
| **LOUD** | `maxEnergy > signalMid × 4` | 외부 소음 (클락션, 유튜브 등) -- 녹음 제외 |
| 통과 | 그 사이 | STT 파이프라인으로 전달 |

- `signalMid`는 실시간 적응형 EMA -- 환경에 따라 천장이 자동 조정됨
- 속삭임이 물리적으로 낼 수 없는 에너지 -> 무조건 외부 잡음

### Stage 2: Band Rank Code (발음 해석 단계)

**밴드별 에너지의 절대값이 아닌 순위를 코드화한다.**

기존 (절대값 토큰):
```
조용한 "ㅅ" -> 0x01020300
큰 "ㅅ"   -> 0x050A0F00   <- 같은 발음인데 다른 코드!
```

순위 기반 토큰:
```
조용한 "ㅅ" -> 밴드6 > 밴드5 > 밴드3 > ...
큰 "ㅅ"   -> 밴드6 > 밴드5 > 밴드3 > ...   <- 동일!
```

**핵심 원리: 볼륨 불변량**
- 마이크 거리, 배경 잡음, 볼륨이 변해도 특정 발음의 밴드 에너지 순위는 변하지 않는다.
- 이것 자체가 강력한 노이즈 필터.

### Stage 3: Rank Set Matching (패턴 매칭 단계)

순위가 흔들려도 **상위 밴드 조합(집합)**으로 매칭한다.

```
"ㅅ" 패턴 = {6-5, 5-6}   <- 1등과 2등이 뒤바뀌어도 같은 발음
"ㅁ" 패턴 = {1-2, 2-1}
```

- 1등은 거의 확정, 2등도 꽤 안정적 -- 하위로 갈수록 애매해짐
- 상위 2~3개의 **순서 없는 집합** = 발음 시그니처
- 경험 DB에 쌓이면 자동 클러스터링 가능

### 3중 필터 통과 = 신뢰할 수 있는 발음 코드

```
원본 오디오
  -> [Stage 1] 에너지 범위 밖 제거 (QUIET/LOUD)
    -> [Stage 2] 순위 코드화 -- 볼륨 노이즈 제거
      -> [Stage 3] 조합 매칭 -- 순위 노이즈 제거
        -> 발음 코드 (이게 틀리면 아예 다른 발음을 낸 것)
```

### 8밴드 주파수 설계 철학

| # | 범위 (Hz) | 이름 | 역할 |
|---|-----------|------|------|
| 0 | 70–1021 | VxLip | **성대음 스위치** -- 유성/무성 판별 (VOICE vs WHSPR) |
| 1 | 1021–1397 | Pharx | 인두 공명 |
| 2 | 1397–1699 | Velar | 연구개 + 모음 ㅏ |
| 3 | 1699–2647 | OralR | 구강 공명 |
| 4 | 2647–3557 | HiRes | 고포먼트 |
| 5 | 3557–4919 | Burst | 치경 파열/마찰 |
| 6 | 4919–7507 | Sibil | 치찰음 분사 |
| 7 | 7507–11197 | Breth | 기식음 + 노이즈 게이트 |

- **Band 0은 스위치**: 성대가 울리면 에너지 高 -> VOICE, 안 울리면 低 -> 속삭임 후보
- **Band 1~7은 발음 포지셔닝**: 속삭임에서 각 발음의 에너지 분포 위치를 구분하는 7축
- 성대음(Band 0) 없이 Band 1~7의 순위만으로 발음을 식별하는 것이 속삭임 인식의 핵심

각 단계에 검증된 알고리즘 적용:
- **스펙트럼 추출**: FFT (이미 구현)
- **발음 특징 추출**: MFCC (밴드 순위와 사촌)
- **패턴 매칭**: DTW (동적 시간 워핑)

---

## 2. 음원 분리 (스테레오 이상 필수)

### 물리 위치 기반 음원 추출

스테레오 마이크의 **좌우 위상차**로 음원 방향을 추정하고,
해당 방향에서 발생한 모든 음을 분리한다.

#### 원리

1. 가장 에너지가 큰 스펙트럼 피크를 찾는다
2. 위상차로 해당 피크의 **물리 위치(발성키)** 를 구한다
3. 계산된 위상차만큼 한쪽 음원을 **시간 시프트**
4. 두 채널에서 **동시에 움직이는 파장은 강화** (보강 간섭)
5. **다르게 움직이는 파장은 약화** (상쇄 간섭)
6. -> 해당 발성키가 발사한 전체 음원이 추출됨

#### 속삭임 분리 적용

```
원본 스테레오 입력
  -> [GCC-PHAT] 위상차 상관으로 음원 위치 추정
    -> [빔포밍 MVDR] 고에너지 음원 방향으로 시프트 -> 보강/상쇄로 추출
      -> 추출된 음원의 에너지 > 속삭임 범위? -> 통째로 제거
        -> 남은 신호 = 속삭임
```

- 같은 프레임에서 **잡음만 골라 빼는 수술** (Stage 1의 프레임 단위 버리기와 다름)
- 노이즈캔슬링 이어폰과 같은 원리, 소프트웨어 구현

#### 마이크 요구사항

| 채널 | 능력 |
|------|------|
| **모노** | 위치 추정 불가 -- Stage 1 문지기만 가능 |
| **스테레오** | 좌우 방향 추정 (위상차) |
| **트리오+** | 삼각측량으로 정확한 2D/3D 위치 |

---

## 3. 멀티플레이어 확장

### 물리 위치 = 플레이어 ID

음원 분리로 얻어진 **발성키(물리 위치)**를 그대로 멀티플레이어 식별자로 사용한다.

```
왼쪽 사람 -> 발성키 A -> Player 1
오른쪽 사람 -> 발성키 B -> Player 2
```

### 발성 모드 = 입력 채널

| 모드 | 용도 |
|------|------|
| **일반 발성** | 위치 추적 -- 누가 말하는지 식별 |
| **속삭임** | 컨트롤 명령 -- 몰래 조작 |

- 키보드/패드 없이 음성만으로 다중 사용자 컨트롤러
- 소리 지르며 위치 잡고, 속삭여서 명령 내리는 파티 게임 등

---

## 4. 구현 로드맵

### Phase W1: 모노 프로토타입 (현재)
- [x] FFT 8밴드 스펙트럼 분석
- [x] Energy Gate -- QUIET/LOUD 문지기
- [x] WhisperRing 시각화 (가중평균 벡터 바늘)
- [x] 토큰 기반 경험 DB 축적
- [ ] 밴드 순위 코드화 (기존 토큰과 병행 실험)
- [ ] 순위 집합 패턴 매칭

### 학습 데이터 전략

- **LOUD/VOICE 데이터** (유튜브, 음악 등): 일반 음성에 섞인 속삭임 성분 포함
  -> 범용 한국어 발음 코드 기초 사전 구축 (대량 데이터)
- **WHSPR 데이터** (내 속삭임): 개인 발음 특성
  -> 개인화 미세 조정 (소량 데이터)
- **모든 모드 녹음 필수**: QUIET만 제외, LOUD도 WAV + 토큰 JSONL 계속 축적
  -> 모드 태그로 구분되므로 나중에 용도별 필터링 가능

### Phase W2: 스테레오 확장
- [ ] 스테레오 마이크 원본 입력 (WASAPI 리샘플 우회)
- [ ] GCC-PHAT 위상차 음원 위치 추정
- [ ] 빔포밍 음원 분리
- [ ] 물리 위치별 발성키 할당

### Phase W3: 멀티플레이어
- [ ] 다중 발성키 동시 추적
- [ ] 일반 발성/속삭임 모드 분리
- [ ] 플레이어별 컨트롤 매핑

### 참고: Android 트리오 마이크
- AudioRecord API: 스테레오까지는 지원, 3채널+는 기기 의존적
- 빔포밍 raw 데이터는 HAL 레벨 -- 앱 접근 제한적
- Fold5 등 폴더블: 마이크 배치 유리하나 API 제약 있음
