Hitman 2: 최신 CPU에서 잔향(Reverb) 향상시키기

게임 오디오 / 공간 음향 / Wwise에 대한 팁과 도구

6 코어와 8 코어 CPU의 대중화는 아직 손대지 않은 여유 처리 능력을 게임에 사용할 수 있게 된다는 것을 의미하며, 그 중 일부를 플레이어의 오디오 환경을 향상시키는 데 사용할 수 있습니다. 추가 코어를 활용하려면, 개발자가 공격적으로 코드를 병렬로 실행하고 게임 기능이 서로 다른 CPU에서 올바르게 확장되도록 해야 합니다. 이 백서에서는 IO Interactive*와 Intel의 공동 작업을 기반으로 멀티코어 CPU를 사용하고 병렬화를 통해 Hitman 2*의 사운드가 보다 몰입적으로 들리게 한 방법을 보여 줍니다. 좀 더 구체적으로, 게임 오디오의 중요하고 계산적으로 비용이 많이 드는 영역인 잔향(reverb)를 개선하는 것에 대해 이야기합니다.

Hitman 2에 대하여

코펜하겐에 본사를 둔 IO Interactive가 개발해 2018년 11월 출시한 스텔스 비디오 게임 'Hitman 2'는 전 세계 수백만 명의 팬들을 끌어모은 프랜차이즈의 연속작입니다. 우리의 플레이어는 암살자 Agent 47의 컨트롤을 맡아서, 넓고 강렬한 레벨을 탐색하고, 중요하고 잘 보호되는 목표물을 흔적 없이 제거하는 창의적인 방법을 찾아내야 합니다.

다른 게임 캐릭터로 위장한 채 목표물에 조심스럽게 접근할 것인지, 사고로 조작할 것인지, 아니면 총구를 활활 불태우면서 임무를 완수할 것인지는 전적으로 플레이어의 몫입니다. 이 게임은 Coop 및 Versus 멀티플레이어 모드를 통해 다른 사람과 협동 또는 대항해서 플레이할 수 있는 능력뿐만 아니라 모든 접근 방법을 위한 충분한 기회를 제공합니다. Hitman 2는 새로운 위치, 미션, 콘텐츠가 정기적인 업데이트로 추가되면서 계속 성장하는 살아있는 세계관입니다.

1 

이 게임은 독점적인 Glacier 게임 엔진과 Wwise를 오디오 미들웨어로 사용하여 개발되었습니다. 따라서 이 기사의 많은 구현 세부 사항은 Wwise에 한정되어 있지만, 어떠한 사운드 엔진에도 쉽게 적용할 수 있습니다.


단순한 잔향 시스템 및 그것의 단점

잔향(Reverb)은 음파가 주변 표면에서 반사될 때 발생하는 현상입니다. 이러한 반사는 소리를 증폭시키고 색소음을 발생시키며, 원래의 직접적인 음파가 희미해진 후에도 지속되게 합니다. 비디오 게임에서, 잔향은 플레이어들에게 행동이 전개되는 환경에 대한 청각적인 단서를 주는 중요한 몰입 도구입니다. 반향된 소리에 기여하는 수많은 반사를 고려할 때, 이 현상의 정확한 시뮬레이션은 계산적으로 매우 비싼 비용을 요구합니다. 따라서, 게임 개발자들은 다양한 근사치에 의존해야 합니다.

개발자들에게 보통 인기 있는 접근법은 게임 세계를 공간적으로 분리된 영역으로 세분화하고 각 영역에 잔향 프리셋을 할당하는 것입니다. 이 글은 Glacier 및 Wwise 용어와의 일관성을 위해, 룸(Room)이라고 영역을 언급합니다. 비록 그것들이 밀폐된 공간을 반드시 나타내는 것은 아니지만 말입니다. 이러한 맥락에서 룸은 유사한 음향 속성을 가진 게임 레벨의 일부입니다. 결과적으로, 실내와 실외 환경 그리고 심지어 열린 지형의 일부를 나타내는 수준의 물리적 구조를 대략 모방합니다. Hitman 2에서는 그림 1과 같이 경계 상자, 원뿔 및 볼록 다각형과 같은 3D 모양을 사용하여 정의됩니다.

2

그림 1입니다. 음향 기하학(sound geometry)의 매우 간단한 예입니다. 이 경우 빨간색으로 강조된 오두막 전체가 하나의 사운드 룸으로 표현됩니다.

잔향 프리셋은 특정 룸의 음향 시뮬레이션을 위해 세밀하게 조정된 사전 정의된 설정의 잔향 효과입니다. 사용된 효과는 합성 잔향(Wwise RoomVerb 같은) 또는 컨볼루션 잔향(convolution reverb)이 될 수 있습니다. Hitman 2는 대부분 후자를 사용합니다.

합성 효과(synthetic effect)는 딜레이 선과 Comb, All-Pass 등의 필터를 사용하여 알고리즘으로 잔향을 시뮬레이션합니다. 이러한 효과는 CPU를 덜 사용하지만, 특히 음향 성능이 복잡하고 잔향 시간이 긴 룸의 경우, 컨볼루션 잔향보다 덜 자연스럽고 미적으로 덜 만족스럽게 들리는 경향이 있습니다. 또한 만족스러운 결과를 얻기 위해 설정하기가 더 어려운 경향이 있습니다.

반면에,  컨볼루션 잔향(convolution reverb)은 실제 위치의 사전 녹음된 임펄스 응답(impulse response)을 사용합니다. 스파크나 스타터 권총 사격과 같은 짧은 소리를 연주하고, 룸의 음향 반응을 녹음함으로써 임펄스 응답이 만들어집니다. 결과 오디오 샘플은 컨볼루션 연산을 사용하여 게임 내 소리에 적용되어 해당 방에서 재생되는 것처럼 보입니다. 컨볼루션 잔향은 CPU에 무겁고 메모리에 무거우며, 임펄스 응답을 구매하거나 찾기 또는 녹음해야 하므로 비용이 많이 들거나 시간이 많이 소요될 수 있습니다. 하지만 일단 임펄스 반응이 좋으면, 그것은 놀랍도록 좋게 들리고, 설득력 있게 들릴 것입니다. 심지어 복잡한 음향 환경도 재현할 수 있고, 적은 조정과 튜닝이 필요합니다.

이 게임은 오디오 리스너가 어느 룸에 있는지 지속적으로 확인하고 현재 재생 중인 모든 3D 사운드에 해당 룸에 할당된 잔향 프리셋을 적용합니다. 리스너는 일반적으로 플레이어가 제어하는 캐릭터의 머리나 게임 카메라에 위치합니다. 이 솔루션은 구현이 간단하고 상당히 효과적이며, Hitman 시리즈를 비롯한 많은 게임에서 사용되어 왔습니다. 하지만, 그것은 또한 매우 초보적이고 몇 가지 중요한 단점이 있습니다.

한 가지 단점을 간단한 예로 증명할 수 있습니다. 작은 콘크리트 벙커에 몸을 숨기고 언덕이 많은 시골에서 당신을 향해 총을 쏘는 적들과 싸우는 게임 캐릭터라고 상상해 보세요. 우리의 간단한 해결책은 당신의 적들의 총소리와 당신 자신의 무기 소리에 벙커의 잔향을 적용할 것입니다. 열려있고 언덕이 많은 구역과 관련된 에코가 많은 잔향 대신, 적들의 사격은 마치 콘크리트 벙커 안에서 발사된 것처럼 쿵 하는 금속성 울림을 갖게 될 것입니다. 이것은 플레이어가 소리 환경을 올바르게 표시하지 않으며, 부자연스럽게 느낄 수 있습니다. 실제 세상에서는 들판에서 들려오는 소리는 우선 언덕에서 반사되는 소리와 메아리로 색칠되고 보완되며, 플레이어의 벙커 벽에서 반사되는 소리보다 더 큰 범위까지 보완됩니다.

이 문제를 해결하려면, 각 소리의 잔향이 리스너로 전달될 때 발생하는 표면으로부터의 반사를 시뮬레이션해야 합니다. 다시 말하지만, CPU에 매우 무거울 것입니다. 하지만 우리는 리스너에게 도달하기 전에 어떤 룸이 소리를 횡단하는지 알아내고, 그 소리 위에 있는 룸들의 잔향 프리셋을 체인으로 묶는 것으로 이것을 대략적으로 계산할 수 있습니다. 각각의 개별적인 소리에 소리 이미터(emitter)가 있는 룸의 잔향을 적용하기만 해도, 많은 경우, 모든 소리에 리스너 룸의 잔향을 적용하는 것에 비해 더 나은 공간적인 단서를 줄 수 있습니다.

그림 2의 시연 영상에서 다양한 잔향과 이를 Hitman 2의 소리에 적용하는 방법을 확인하세요.

그림 2입니다. 오디오 기능이 설명되었습니다 : 잔향에 대한 이 비디오는 제가 이 섹션에서 설명한 내용을 보여줍니다.

소리가 전달되거나 전달되는 위치의 잔향을 사용하면 다음과 같은 몇 가지 문제가 발생합니다.

  • 잔향 효과를 렌더링하는 CPU 비용
  • 룸 탐지
  • 잔향 체인
  • 잔향 방향성
  • 다른 CPU에서 확장

이것들 각각에 대해 자세히 살펴보겠습니다.

잔향 효과를 렌더링하는 CPU 비용

잔향 효과는 CPU에 큰 영향을 미치기 때문에, 게임이 동시에 작동하는 효과 인스턴스 수를 최소화하는 것이 필요합니다. 따라서, 잔향 효과는 일반적으로 개별적인 소리에는 적용되지 않습니다. 대신, 일정한 잔향 효과가 필요한 소리는 이를 서브믹스하여 원하는 효과를 한 번 적용하는 이른바 보조 버스(auxiliary bus)로 라우팅 됩니다. 각 소리의 잔향 강도는 특정 볼륨, 이른바 송신 값(send value)으로 소리를 확장하는 것만으로도 제어됩니다. 이것은 대부분의 게임에서 표준 관행입니다. Wwise에서 라우팅은 SetGameObjectAuxSendValues API를 사용하여 사운드 이미터에서 수행됩니다.

Hitman 2에는 그림 3과 같이 일반적인 환경을 나타내는 수십 개의 잔향 버스가 있습니다. 게임의 각 룸에는 사운드 디자이너에 의해 이러한 버스 중 하나가 할당됩니다.

3그림 3입니다. 저희의 Wwise 프로젝트의 잔향 버스 계층 구조입니다.

버스에 대한 효과는 해당 버스가 활성 상태일 때, 다시 말해 재생 소리가 라우트 될 때에만 렌더링 됩니다. 재생음이 없는 버스는 휴면 상태이며 그 효과는 일반적으로 CPU를 사용하지 않습니다. 예외는 버스로 라우팅 된 모든 소리가 종료되었지만 버스가 활성 상태를 유지하여 잔향과 같은 효과에 의해 생성된 꼬리를 재생하는 것을 마칠 때입니다.

이전 솔루션의 CPU 풋프린트

이전 솔루션은 CPU 사용량 측면에서 저렴합니다. 모든 소리를 리스너 룸의 버스로 라우팅하는 것은 하나의 잔향 효과만 렌더링 한다는 것을 의미합니다. 동시에 둘 이상의 활성 버스가 리스너가 룸을 연결하는 포털(예: 문이나 다른 열리는 곳) 근처에 서 있을 때 발생합니다. 그럴 경우, 우리는 소리를 리스너 버스뿐만 아니라 인근 포털의 반대편에 있는 룸의 버스에도 전달해야 합니다. 이렇게 하면 리스너가 한 룸에서 다른 룸으로 이동할 때 부드러운 잔향 전환이 가능합니다. 그럼에도 불구하고 활성 버스 수는 두 개 또는 세 개를 절대 초과하지 않으므로, 사용된 효과의 CPU 비용은 덜 관련되게 됩니다.

우리의 새로운 솔루션의 CPU 풋프린트

그것들이 위치해있는 룸의 버스로 소리를 라우팅 하기 시작하면 다른 그림이 되게 됩니다. Hitman 2에서 동시에 재생되는 소리(보이스 캡)의 최대 수가 64개이므로, 각각의 소리가 고유한 버스를 가지고 자신의 룸에 있다면 이론상으로는 64개 정도의 활성 잔향 버스로 끝날 수 있습니다. 실제로 이러한 최악의 시나리오는 매우 가능성이 낮지만, 활성 잔향 버스 수는 한 번에 평균 약 8-10개로 이전 솔루션보다 더 높습니다. 예를 들어 그림 4에서 Wwise Advanced Profiler의 스크린샷을 보면 활성 잔향 버스와 각 버스에 믹스되는 소리 수가 표시됩니다(Mix Count 열).

4그림 4. 활성 잔향 버스. 일부 버스는 Mix Count가 0인 경우에도 활성화된다는 점에 유의하십시오. 그들은 이미 끝난 소리의 잔향 꼬리를 재생하고 있습니다.

8~10개의 잔향이 생기는 경우가 이전 솔루션의 2-3개와 큰 차이가 없는 것처럼 보일 수도 있습니다. 그러나 저희는 잔향 인스턴스 수에 따라 선형적으로 확장되는 CPU 비용이 높은 컨볼루션 잔향을 사용합니다. 따라서 새 시스템으로 전환하면 총 오디오 프레임 렌더링 시간이 잔향 설정에 따라서 50% 이상 늘어납니다. 따라서 재생할 사운드 데이터가 하드웨어에서 떨어지기 전에 렌더링을 수행하지 않는다면 버벅임을 발생시킬 수 있고, 혹은 적어도 초당 프레임(fps)에 부정적인 영향을 줄 수가 있습니다.

오디오 렌더링 병렬 처리하기

좋은 소식은 잔향 버스는 서로 의존하지 않고, 그 효과는 버스 자체의 서브 믹스 버퍼에 쓰여진다는 것입니다. 따라서, 그들은 병렬 실행의 완벽한 후보입니다. 여러 하드웨어 스레드에서 동시에 잔향 효과를 렌더링 하면 증가된 잔향 인스턴스의 부정적인 영향을 줄이거나 완전히 없앨 수 있기 때문에, 이것이 바로 현대의 멀티 코어 CPU를 활용할 수 있는 부분입니다.

우리는 Wwise를 사용하기 때문에, 이것을 무료로 받습니다. Intel 엔지니어가 구현한 작업 기반 오디오 렌더링은 버전 2018.1 이후 표준 SDK(Wwise 소프트웨어 개발 키트)에 포함되어 있습니다. 오디오 렌더링 파이프라인을 병렬로 수행할 수 있는 일련의 세분화된 작업으로 분해하고 게임에서 이를 실행하도록 요청합니다. 우리는 이러한 작업을 우리의 작업 스케줄러에 넣을 수 있는데, 그림 5에서 보이는 것처럼 현재 사용 가능한 워커 스레드에서 실행을 해주는 것입니다. 이 작업 스케줄러는  작업 스케줄러입니다. Wwise를 사용하지만 작업 스케줄러가 없는 게임은 SDK에서 제공하는 샘플 구현을 이용할 수 있습니다(TaskScheduler 샘플 참조). 사용하기 위해서는 거의 작업이 필요하지 않으며, 오디오 프레임 렌더링 시간의 개선은 매우 괄목할 만큼 됩니다.

5그림 5입니다. 이 Glacier 프로파일러 스크린샷은 Hitman 2에서의 일반적인 오디오 프레임의 병렬 렌더링을 보여줍니다. "JqWorker"라는 제목이 붙은 수평 라인은 작업자 스레드이지만, 빨간색과 노란색 항목은 이러한 스레드에서 실행되는 개별 작업(Glacier 용어로는 "jobs")을 나타냅니다. 화면의 보기는 오디오 작업만 표시하도록 필터링 된 것입니다.

성능 비교

병렬 오디오 렌더링을 사용하는 경우와 사용하지 않는 경우의 성능을 살펴봅시다. 이 비교를 위해 그림 6에 나타낸 위치에서 아이들(idle) 상태의 평균 오디오 프레임 렌더링 시간을 측정했습니다.

6그림 6. 성능 측정에 사용된 히트맨 2의 Miami 레벨 지점

첫 번째 테스트 사례에서는 이전 잔향 시스템이 활성화됩니다. 테스트 위치는 포털 근처에 있으므로 두 개의 활성 잔향이 있습니다. 두 번째 테스트 사례에서는 새로운 솔루션으로 전환합니다. 이 솔루션으로 인해 여덟 번의 활성 잔향이 발생합니다. 마지막으로, 우리는 새로운 시스템이 최고 품질의 잔향 프리셋과 결합되었을 때 어떤 일이 일어나는지 보여줍니다. 이 프리셋은 가장 좋게 들리지만 가장 느립니다.

모든 경우에서, Wwise Convolution Reverb 효과가 사용되었습니다. 이 플러그인에 익숙한 사용자들을 위해, 처음 두 테스트에서 사용된 프리셋은 모노 임펄스 응답(IRs)과 한계점이 -50dB인 반면, 마지막 테스트의 경우 스테레오 IR과 한계점 -144dB인 프리셋으로 전환하였습니다. 일반 프리셋과 고품질 프리셋에서 사용되는 IR의 길이는 동일하며 프리셋마다 1초에서 3초까지 다양합니다.

7

그림 7은 6코어 CPU가 장착된 PC에서 이러한 테스트의 결과를 보여줍니다.

보시다시피 병렬 오디오 렌더링을 사용하면 비병렬 버전에 비해 첫 번째 테스트에서는 1.45배, 두 번째 테스트에서는 2배, 세 번째 테스트에서는 1.9배 향상됩니다. 더욱 중요한 것은, 각 인스턴스의 CPU 비용과 잔향 인스턴스의 수가 증가함에 따라 확장성이 향상된다는 것입니다.

테스트 PC에서는 각 작업에 평균 60마이크로초가 소요되었으며, 이는 상당히 우수한 작업 세분성입니다. Convolution reverb 작업은 주목할 만한 예외이며, 최고 품질의 사전 설정으로 효과를 렌더링 하는 데 1밀리초(ms)의 시간이 소요되었습니다. 하지만, 고품질 잔향이 8번 있는 가장 값비싼 테스트 사례에서도, 모든 코어에 오디오 작업을 실행하는 데 걸린 게임 프레임당 총 시간은 싱글코어의 오직  평균 17%이었습니다. 이는 오디오 작업이 각 코어에서 상대적으로 적은 시간을 차지하여 대부분의 CPU 리소스가 다른 게임 작업에 사용된다는 것을 의미합니다.

Xbox One* 및 PlayStation 4*에서 동일한 테스트가 어떻게 수행되는지 대략적으로 파악하려면 그림 7로부터 4를 곱해 보세요.

그림 8은 코어 수가 서로 다른 CPU에서 병렬화하여 얻을 수 있는 성능 향상 효과를 비교합니다. 이는 동시 실행이 코어 수가 4개 및 6개로 구성된 구형 CPU에서도 개선되도록 하고 있고, 현대적인 8코어 CPU에서는 가장 큰 이점을 누리고 있음을 분명히 보여줍니다.

8그림 8입니다. 코어 수가 서로 다른 Intel® Core™ 프로세서의 동시성을 통해 성능을 향상시킵니다. 각 테스트 사례와 CPU에 대해, 동기식 오디오 프레임 렌더링 시간을 병렬 렌더링 시간으로 나누어 게인율을 계산합니다.

룸 탐지

어떤 잔향 버스에 소리를 공급해야 하는지 판단하려면, 우리는 그 소리가 있는 방을 찾아야 합니다. 이를 위해 특정 지점(사운드 방사체 위치)에서 빠르게 조회할 수 있는 공간 구획 데이터 구조에 룸을 저장합니다. 이 알고리즘은 GDCE(Game Developers Conference Europe) 2015 강연 "Sound Propagation In Hitman"에서 자세히 설명되어 있습니다.

구현은 간단합니다. 중첩되거나 겹치는 여러 환경 중에서 올바른 환경을 선택하는 것이 유일한 주의 사항입니다. 룸에 우선순위를 지정하여 이 작업을 수행할 수 있습니다. 가장 바깥쪽 룸의 우선순위가 가장 낮아야 하는 반면, 가장 안쪽 룸의 우선순위는 가장 높습니다. 우선순위는 자동으로 계산되어야 하며, 미세 조정을 위해 편집기에서 수동으로 오버라이드 할 수 있는 옵션이 있어야 합니다.

또 다른 생각해 볼 것은 음향 방출기가 한 방에서 다른 방으로 이동할 때 갑작스런 잔향의 변화를 막는 것입니다. 이 작업은 근처 포털로 이동하여 사운드 방사체를 포털의 반대편에 있는 룸 버스로 라우팅함으로써 수행됩니다. 이 경우 전송 값은 소리 방사체와 다른 룸으로 이어지는 가장 가까운 개구부 사이의 거리 인자입니다.

이를 구현하기 위해서는, 특정 지점의 거리 내에 포털 목록을 얻을 수 있는 효율적인 방법이 필요합니다. 따라서, 우리는 포털을 나타내는 지오메트리를 룸에 사용하는 것과 동일한 유형의 공간 분할 구조로 저장합니다.

모든 프레임의 모든 소리에 대해 룸 및 인근 포털을 쿼리하고 적절한 버스로 라우팅해야 합니다. 지오메트리가 바뀌지 않았다고 가정할 때 위치가 바뀌지 않은 소리에 대해서는 피하는 것이 좋습니다. 그러나 이러한 작업 중 일부는 여전히 수행할 수 있으며, 상대적으로 가벼운 반면, 메인 스레드의 바람직하지 않은 오버헤드가 추가될 수 있습니다. 따라서 작업자 스레드에 오프로드 하는 것이 좋습니다.

한 가지 방법은 모든 쿼리를 하위 집합으로 세분화하고 각 하위 집합을 자체 작업에서 처리하는 것입니다. 작업 수는 작업자 스레드 수와 일치해야 하므로, 이 값을 고려하여 부분 집합 크기를 선택합니다. 쿼리를 실행하는 동안 새 이미터가 생성되지 않도록 게임 논리 업데이트가 완료된 직후 작업을 예약합니다. 오디오 명령 대기열을 처리하거나 Wwise를 사용하는 경우 RenderAudio에 대한 호출을 시작하기 전에 완료해야 합니다.

그러나 더 좋은 방법은 전체 사운드 이미터 업데이트 루틴을 개별 작업으로 만들고 이러한 작업을 작업자 쓰레드에서 병렬로 실행하는 것입니다. 여기서 업데이트 루틴은 각 프레임의 메인 스레드에서 각 재생 사운드 이미터에 대해 수행하는 계산에 대한 집합 이름입니다. 여기에는 차단, 회절, 체적, 도플러 및 잔향 계산이 포함될 수 있습니다.

잔향 체인

소리가 전달되는 룸의 잔향을 리스너에게 적용하려면 룸의 버스를 체인으로 묶어야 합니다. A 룸에 소리가 있고 C 룸에 듣는 사람이 있다고 가정해 보겠습니다. A 룸과 C 룸은 B 룸을 통해 연결됩니다. 먼저 소리를 A의 버스로 전송합니다. 그 버스는 B의 버스와 연결되고, 후자는 C의 버스와 연결됩니다. 그 결과, 그 소리는 그것이 통과하는 세 개의 룸 모두에서 되돌아오는 잔향에 의해 영향을 받습니다.

성능 참고 사항 : 세 개의 룸 모두 소리 수에 상관없이, 활성 버스 수는 여전히 세 개입니다. 하지만 모든 재생 소리가 다른 룸에 있거나 여러 다른 방에 전달된다면, 여러분은 곧 너무 많은 활성 버스를 얻게 됩니다. 이 경우 로직을 구현하여 카운트를 줄여야 합니다. 예를 들어, 전체 믹스에 큰 영향이 없을 것으로 기대되면 사운드를 버스로 라우팅하지 않도록 선택함으로서요.

앞서 언급한 GDCE 강연에서 설명한 전달 시스템을 확장하여 각 전달 경로의 여러 전달 경로와 룸을 추적할 수 있습니다. 일단 그 정보를 얻게 되면, 버스 라우팅을 설정하는 것은 오히려 사소한 일입니다.

Wwise에서 버스 라우팅 설정

Working With the New 3D-Bus Architecture in Wwise 2017.1 : Simulating an Audio Surveillance System이라는 제목의 Audiokinetic의 블로그 게시물에서 설정에 대해 자세히 설명합니다. 오디오 보안 감시 시스템을 구현하는 것에 대한 예이긴 하지만, 잔향 체인을 설정하는 경우에도 동일한 원칙이 적용됩니다. 잔향 버스에서 Listener Relative Routing(Wwise 2018.1전에는 Enable Positioning)을 활성화하고 각 룸에 대해 사운드 이미터를 등록한 다음, SetListeners API를 사용하여 한 룸 이미터에서 다른 룸 이미터로 소리를 라우팅해야 합니다. 마지막으로, SetGameObjectAuxSendValues API를 사용하여 일반 사운드 이미터에 대해 잔향 버스 라우팅을 설정할 때, 그 일반 이미터가 위치한 룸의 이미터 ID에 AkAuxSendValue::listener를 설정합니다.

전달 시스템 병렬화 하기

Hitman (2016)을 위해 쓰여진 원래의 전달 시스템은 폐쇄와 회절을 계산하는 데만 사용되어 왔기 때문에, 그것은 단지 어떤 룸에서 리스너의 룸으로 들어가는 최고의 전달 경로를 찾는 것에만 관심을 두었을 뿐입니다. 그 결과, 전달 시스템을 업데이트하는 데에는 프레임당 0.1ms 정도 소요될 정도로 비용이 저렴했고, 메인 스레드에서 진행하기도 했습니다. 하지만 소리가 리스너에게 전달될 수 있는 여러 경로를 추적하는 것은 비용이 더 많이 들기 때문에 작업자 스레드에 오프로드 하는 것이 타당했습니다.

이 작업을 수행할 때 일반적으로 고려할 사항은 언제라도 다른 스레드에서 업데이트가 완료될 때까지 기다리도록 하지 않는 것입니다. 저희는 다음과 같은 두 가지 간단한 트릭을 사용하여 이를 달성할 수 있습니다.

  • 타이밍: 전파 시스템 업데이트는 카메라와 게임 캐릭터 위치를 업데이트한 후 프레임 초반에 예약됩니다. 이때 리스너의 위치가 알려지게 됩니다. 이렇게 하면 프레임 끝에 있는 오디오 시스템 업데이트에 전달 데이터가 필요하기 전에 전달 작업을 완료할 수 있습니다.
  • 전달 데이터를 이중 버퍼링 하기 :  게임 루프가 생성하는 새로운 사운드는 업데이트되는 동안 전달 시스템을 쿼리할 수 있으므로, 마지막 프레임에서 전달 데이터를 캐쉬하여 현재 프레임 전체에 제공합니다. 전달 데이터는 오디오 시스템이 업데이트되기 전에 프레임 끝에서 스와프 됩니다.

잔향 방향성

오래된 단일 잔향 솔루션과 관련된 중요한 문제이지만, 새로운 솔루션에도 더욱 해당되는 이야기인데요, 게임에 사용되는 대부분의 잔향 효과가 단일 채널이기 때문에 소리의 방향성을 보존하지 못한다는 것입니다. 이 작업은 성능상의 이유로 수행됩니다. 결과적으로 소리가 나는 방향과 상관없이 모든 스피커에서 잔향이 들리게 됩니다. 예를 들어 비플레이어 캐릭터(NPC)가 게임 캐릭터의 왼쪽에 총을 발사했다고 가정합니다. 직접적인 소리는 왼쪽에서 분명히 들리게 되겠지만, 그 잔향은 사방에서 나오는 것처럼 보일 것입니다. 소리와 리스너 모두가 같은 밀폐된 공간에 있다면 이것은 괜찮지만, 실질적으로 다른 어떤 경우에라도 우리는  방향성과 잔향의 확산을 통제하고 싶습니다. 이것은 많은 잔향이 동시에 활성화될 때 특히 그렇습니다. 방향성의 결여는 한두 번의 잔향에 의해 용인될 수 있지만, 많은 전방위적인 경우를 갖는 것은 혼란스럽고 나쁘게 들리는 믹스을 야기할 수 있습니다.

잔향 버스 패닝하기

방향성 문제를 쉽게 해결할 수 있는 방법은 각 룸의 잔향 출력을 독립형 3D 사운드로 처리하고 패닝과 확산을 사용하여 방향과 볼륨을 제공하는 것입니다.

Wwise에서 이를 구현하는 단계는 Wwise의 Bus Routing Setup 섹션에 설명된 것과 실질적으로 동일합니다. 잔향 버스에서 Listener Relative Routing을 사용하도록 설정하고, 룸에 있는 일반 이미터에 대해 잔향 라우팅을 설정할 때  해당 룸의 이미터 ID를 AkAuxSendValue::listenerID에 할당하여 해당 버스를 룸 이미터와 연결해야 합니다. 이제 룸의 가운데에 룸 이미터를 배치하거나 리스너의 룸으로 연결되는 포털에 룸 이미터를 배치하여 잔향을 패닝할 수 있습니다(더 현실적이지만 더 구현하기 어려움). RegisterBusVolumeCallback API를 사용하여 사용자 커스텀 믹싱을 구현할 수도 있습니다. 이 API는 이미터와 리스너 사이의 거리가 아닌 다른 것에 기반하여 스프레드를 제어하는 Wwise의 유일한 방법이기 때문에 유용합니다.

이 방법의 분명한 단점은 듣는 사람의 룸의 잔향을 이런 식으로 패닝할 수 없다는 것입니다. 룸이 넓은 열린 공간을 표현하는 경우 이 문제가 발생할 수 있습니다. 이렇게 큰 공간을 프로그래밍 방식으로 여러 부분으로 나누고, 각 파트에 대해 사운드 이미터를 만들고, 소리를 각 파트으로 라우팅하여 이 문제를 해결할 수 있습니다. 대형 비-리스너 룸도 마찬가지로 이렇게 할 수 있습니다. 지오메트리 생성 프로세스의 일부로 지오메트리를 분할은 오프라인이 될 수 있습니다.

또 다른 단점은 성능과 관련된 것입니다. 룸당 사운드 이미터를 사용하여 잔향 버스의 위치를 지정함으로서, 각 룸에 대해 활성 버스 인스턴스를 효과적으로 만들 수 있습니다. 이전에는, 동일한 리버스 버스를 사용하는 두 개의 룸이 활성 버스 인스턴스를 공유하여 하나의 잔향 효과만 발생시켰지만, 이제는 각각 고유한 버스 인스턴스를 갖게 되었습니다. 위에서 설명한 것처럼 작은 부분으로 분할하는 지오메트리에도 동일하게 적용됩니다. 각 부분은 버스 인스턴스를 생성합니다. 이것은 지오메트리에 따라 문제가 될 수도 있고 아닐 수도 있습니다.

다중 채널 잔향 효과 사용하기

잔향의 방향성을 유지하는 또 다른 방법은 다중 채널 잔향을 사용하는 것입니다. 수직성을 지원하지 않는 한 4개의 채널이면 충분합니다. 각 소리는 리스너에 상대적인 위치에 대해 잔향 버스 채널에 믹스됩니다. 모든 사운드가 서브 믹스되면 이 프레임에 대한 가청 콘텐츠가 없는 채널을 제외하고, 각 채널에서 개별적으로 잔향 효과가 렌더링 됩니다. 그런 다음, 잔향 버스 채널이 최종 출력 오디오 버스로 믹스됩니다. 이 오디오 버스의 채널 구성은 플레이어의 실제 스피커 설정(스테레오, 5.1, 7.1 등)에 해당합니다.

이 접근법을 사용할 때 잔향 비용은 채널 수로 곱해집니다. 따라서, 모든 활성 잔향 버스에서 이 효과를 사용하는 것은 엄청나게 비쌀 수 있습니다. 최적의 접근 방법은 리스너가 아닌 룸의 경우 모노 잔향 효과와 버스 패닝을 사용하고, 리스너 룸의 경우 다중 채널 잔향 효과를 사용하는 것입니다. 리스너가 인접한 룸으로 통하는 포털에 접근할 때, 부드러운 전환을 위해 해당 룸의 모노 잔향을 다중 채널 버전과 크로스 페이드 해야 합니다.

Wwise는 다중 채널 잔향 효과를 지원하지 않습니다. Wwise Convolution Recoverb에는 Filter 모드가 있으며, Filter 모드는 위에서 설명한 로직과 유사한 방식으로 작동합니다. 하지만, 다양한 채널 구성과 관련하여 유연성이 부족하여 프로덕션에서 사용할 수 없습니다. 또한 이 모드는 잔향을 시뮬레이션하는 데 사용되지 않습니다. 따라서, 다중 채널 잔향을 사용하는 것은 그들 자신의 컨볼루션 잔향 플러그인을 개발하려는 사람들을 위한 옵션입니다. 이러한 플러그인을 구현할 때는, 병렬화를 활용하십시오. 각 채널에 효과를 렌더링 하는 것은 작업자 스레드에서 개별 작업으로 실행되어야 합니다. 이러한 작업은 실행하는 동안 상호 종속성이 없습니다.

다른 CPU에서 확장

Hitman 2에서는, 기존 시스템에 대한 지원을 유지하면서 콘솔에 함께 출시했습니다. 그러나 PC에서는, 플레이어는 오디오 시뮬레이션 품질이라고 하는 세 가지 품질 수준 중에서 선택할 수 있습니다.

  • Base: 향상된 오디오가 없습니다. 물리적 코어 수가 4개 이하인 CPU에서 기본 설정됩니다.
  • Better: 새로운 잔향 시스템입니다. 물리적 코어가 4개 이상인 CPU의 경우 기본값입니다.
  • Best: 개선된 것과 동일하지만 최고 품질의 잔향 설정을 사용합니다. 6개 이상의 물리적 코어가 있는 CPU에서 기본 설정됩니다.

플레이어는 그림 9와 같이 Audio Option에서 오디오 시뮬레이션 품질을 제어할 수 있습니다.

9그림 9입니다. 오디오 시뮬레이션 품질 설정입니다.

Wwise 구현

Wwise에서 잔향 효과에 대한 다양한 품질 수준을 지원하는 것은 그림 10과 같이 잔향 버스 계층 구조를 복제하고 고품질 버스에 더 나은 효과를 사용함으로써 가능합니다. 코드는 시뮬레이션 품질 값에 따라 자동으로 올바른 버스(표준 또는 HQ)를 선택합니다.

10그림 10입니다. 고품질 버스는 일반 잔향 계층 구조를 반영합니다.

유지관리가 더 쉬운 또 다른 방법은, 한 계층을 유지하고 두 효과를 각 잔향 버스에 추가한 다음, 코드에서 설정된 전역적 Real-time Parameter Controls (RTPC)를 사용하여 런타임 시 효과 중 하나를 건너뛰는 것입니다.

어떤 방법을 선택하든지, 불필요한 메모리 사용 오버헤드를 방지하기 위해 효과의 미디어를 다른 사운드 뱅크에 저장하고 시뮬레이션 품질 값에 따라 올바른 미디어를 로드해야 합니다. 그림 11과 같이, 각 레벨마다 다른 컨볼루션 잔향 사운드 뱅크를 사용합니다.

11그림 11입니다. 히트맨 2의 사운드 뱅크 구조입니다.

결론

이 기사에서는 현대 CPU의 여러 코어를 활용하면 높은 컴퓨팅 비용으로 인해 이전에는 액세스할 수 없었던 게임 오디오를 개선할 수 있는 가능성을 어떻게 열 수 있는지 보여줍니다. 여기에 설명된 잔향 시스템의 변경 사항은 Hitman 2의 플레이어에 의해 감지되고 즐겨졌습니다. 오디오 시스템의 병렬화 개선은 CPU 리소스를 확보하였고 오디오 팀과 다른 부서에서 잘 활용하게 되었습니다.

그러나 이 예제는 다중 코어 CPU의 하위 단위의 제한에 여전히 영향을 받습니다. 코어가 8개 이상인 시스템이 광범위하게 채택되고, 게임 개발자가 계산을 병렬화하고, 오디오 미들웨어 생산업체가 벡터링(예를 들어, Intel® Advanced Vector Extensions 2 (Intel® AVX2) 혹은 Intel® Advanced Vector Extensions 512 (Intel® AVX-512))을 활용하기 위한 의식적인 노력이 더 많은 세부 정보와 몰입도를 가져올 수 있습니다.

 
참조
 

This blog was originally written for Intel

 

스테판 보예프 (STEPAN BOEV)

리드 오디오 프로그래머

IO Interactive (IO 인터렉티브)

스테판 보예프 (STEPAN BOEV)

리드 오디오 프로그래머

IO Interactive (IO 인터렉티브)

스테판 보예프는 IO Interactive의 수석 오디오 프로그래머입니다. 비디오 게임 업계에서 14년간 활동하면서, 그는 Hitman, Far Cry, World in Conflict 시리즈를 작업해왔습니다. 그는 복잡한 프로그래밍 문제와 성능 최적화는 물론 게임 오디오의 미학, 몰입, 디테일에 대한 열정이 대단합니다.

댓글

댓글 달기

이메일 주소는 공개되지 않습니다.

다른 글

게임 사운드 보관 | 제 2부: '컨커 최악의 날'과 미스터리한 MP3

오늘 소개할 이야기는 뜻밖의 결과, 다시 말해 우연한 발견에 관한 이야기입니다. 연구 프로젝트가 의도한 대로 끝나지 않았기 때문에 복잡하게 느껴지실 수도 있지만 끝까지...

29.9.2021 - 작성자: 파니 러비야르 (Fanny REBILLARD)

게임 음악은 단순히 그냥 음악이 아니다: 제 2부

게임 음악이란 무엇일까요? 상호작용 음악이란 무엇일까요? 이 질문에 답하기란 생각만큼 그리 간단하지 않습니다. 올리비에 더리비에르(Olivier Derivière)는 이 글을 통해...

27.10.2021 - 작성자: 올리비에 더리비에르 (OLIVIER DERIVIÈRE)

Wwise 2022.1 Unreal 통합 변경 사항

Wwise 2022.1 Unreal 통합 안내 이 버전은 Wwise Unreal 통합의 주요 이정표입니다. Unreal 엔진 5가 엔진을 새로운 차원으로 이끌어주듯이...

9.9.2022 - 작성자: 미셸 도네 (Michel Donais)

노 스트레이트 로드(No Straight Roads)의 음악적 게임 세계 설계하기

안녕하세요, 게임 오디오 여러분들! 저희가 Wwise와 Unreal Engine을 사용해서 '노 스트레이트 로드(No Straight Roads, NSR)'의 극도의 스타일링을...

29.3.2023 - 작성자: Imba Interactive (임바 인터랙티브)

Wwise Spatial Audio 2023.1의 새로운 기능 | 위상 완화 (Phasing Mitigation)

오늘 이 글에서는 '위상(phasing)'이라는 흥미로운 음향적인 현상에 대해 알아보겠습니다. 이 현상은 특정 환경에서 음향을 모델링할 때 나타날 수 있죠. Wwise 23.1의...

25.1.2024 - 작성자: Allen Lee

Unreal Engine에서 Wwise 사운드를 재생하는 방법

Wwise에는 수많은 기능이 있습니다. 하지만 개발 초기에는 사용법에 대한 충분한 정보가 없을 경우 제대로 작동하지 않을 수 있죠. 저는 초기의 몇 가지 삐걱거림 때문에...

30.7.2024 - 작성자: 히로시 고다 (Hiroshi Goda)

다른 글

게임 사운드 보관 | 제 2부: '컨커 최악의 날'과 미스터리한 MP3

오늘 소개할 이야기는 뜻밖의 결과, 다시 말해 우연한 발견에 관한 이야기입니다. 연구 프로젝트가 의도한 대로 끝나지 않았기 때문에 복잡하게 느껴지실 수도 있지만 끝까지...

게임 음악은 단순히 그냥 음악이 아니다: 제 2부

게임 음악이란 무엇일까요? 상호작용 음악이란 무엇일까요? 이 질문에 답하기란 생각만큼 그리 간단하지 않습니다. 올리비에 더리비에르(Olivier Derivière)는 이 글을 통해...

Wwise 2022.1 Unreal 통합 변경 사항

Wwise 2022.1 Unreal 통합 안내 이 버전은 Wwise Unreal 통합의 주요 이정표입니다. Unreal 엔진 5가 엔진을 새로운 차원으로 이끌어주듯이...