ACM 컨볼루션
ACM 컨볼루션은 FMOD의 분할 리버브를 CPU에서 실행합니다. 공유 입력 묶음은 드라이 신호 하나를 변환하고, float 또는 half-float 임펄스 분할을 적용한 뒤, 웻 결과를 중첩 가산합니다.
2026년 10월 10일까지의 저장소 노트
해결한 버그
Subnautica: Below Zero는 지직거림으로 시작해 무음이 되었다가 몇 분 뒤 회복되곤 했습니다. 호스트 장치에 도달하는 PCM에 유한하지 않은 부동소수점 값이 들어 있었습니다. FMOD DSP 콜백의 메모리 내 추적에서 유한한 오디오가 컨볼루션 리버브로 들어가 쓰레기 값이 되어 나오는 것을 확인했습니다. HLE 함수 sceAcm_ConvReverb_SharedInput, 묶음 제출, sceAcmBatchWait가 출력을 쓰지 않고 성공을 반환하고 있었습니다.
그러면 FMOD는 기록되지 않은 웻 버퍼를 그래프에 섞었습니다. NaN이 이후 이펙트로 퍼졌습니다. AudioOut의 정리 장치는 이를 무음으로 바꿨지만 오염된 필터 이력은 고칠 수 없었습니다. 두 번째 오류로 초기 묶음 식별자 -1에 대한 대기가 성공했습니다. FMOD는 초기 대기 실패를 '아직 이전 웻 버퍼가 없음'으로 해석하고, 실제로 완료된 작업 뒤에만 믹스합니다.
분할 컨볼루션
디스크립터 레이아웃은 FMOD의 ACM 백엔드에서 관찰된 것과 일치합니다. 임펄스 응답 분할은 인터리브된 복소수 빈입니다. B개 빈의 블록은 길이 2B의 변환에 속합니다. 입력, 출력, 중첩 버퍼는 별개이며 평면형입니다. 관찰된 오프셋 0 float32와 float16 스펙트럼 레이아웃만 받아들입니다.
묶음은 CPU에서 실행됩니다. 입력 이력은 그레인 사이와 링 순환을 넘어 유지되고, 중첩은 다음 출력 그레인으로 넘어갑니다. 여러 출력이 입력 변환 하나와 이력 전진 하나를 공유할 수 있습니다. 모노 입력이 여러 채널에 공급될 수 있습니다. 역변환은 정규화됩니다. 실제 임펄스 분할을 독립적으로 역변환하자 에너지가 0으로 채운 블록의 앞쪽 절반에 놓였고, 이로써 스펙트럼 부호를 확인했습니다. 게임이 쓰는 패킹된 임펄스는 나이퀴스트 빈을 생략합니다.
대기, 한도, 재테스트
빌더는 포인터 배열과 게인을 한도가 있는 명령 레코드에 담습니다. PCM 자체는 묶음이 시작될 때 읽습니다. 대기는 이 컨텍스트가 실제로 완료한 묶음에 대해서만 성공합니다. 컨텍스트를 파괴하면 이력이 해제됩니다. 잘못된 범위, 알 수 없는 명령 인코딩, 지원되지 않는 레이아웃은 오류를 반환합니다.
단독 ACM FFT, IFFT, 패너 연산은 구현되지 않았습니다. 채널은 8개, 출력은 32개, 블록은 1024로 제한됩니다. 이력 저장 공간에는 한도가 있습니다. 서명 러너에서 초당 한 번 찍은 PCM 스냅샷 90개에 유한하지 않은 샘플은 없었고, 정점은 0.1255, 0.001을 넘는 첫 오디오는 11.03초였습니다. 메인테이너가 소리를 확인했습니다. 이 표본은 프로브일 뿐, 게임이 낸 모든 샘플이 아닙니다.
구현된 것
- FMOD 공유 입력·공유 IR 리버브 묶음을 위한 분할 FFT 컨볼루션.
- float32와 float16 복소 스펙트럼, 중첩 가산, 그레인 간 이력.
- 해당 컨텍스트의 완료된 묶음에 대해서만 성공하는 대기. 초기 식별자 -1은 실패합니다.
- Subnautica 재테스트의 유한한 PCM. 지직거림과 이후의 무음이 사라졌습니다.
아직 빠진 것
- 단독 ACM FFT, IFFT, 패너 호출은 구현되지 않았습니다.
- 0이 아닌 스펙트럼 오프셋과 측정되지 않은 라우팅 레이아웃은 거부됩니다.
- 컨볼루션은 CPU에서 실행됩니다. GPU FFT 경로는 없습니다.
관련 메커니즘
이 페이지들에 대하여