본문으로 바로가기

7장 Audio - ③ FMOD를 활용한 오디오 믹싱 및 이펙트

오디오는 게임에서 중요한 역할을 차지한다. 게임 플레이 상황에 대한 오디오 신호를 제공한다든지 게임의 전반적인 분위기를 강화하는 역할 등 퀄리티 높은 사운드는 게임에 많은 생명력을 부여한다. 이번 장에서는 오디오 관련 강력한 기능을 제공하는 FMOD API를 활용하여 게임에서 다양한 오디오를 추가하는 방법을 다룬다.

💡 7장의 목차

  • 오디오 구축하기
  • 3D 위치 기반 오디오
  • 믹싱 및 이펙트

믹싱 및 이펙트

디지털 신호 처리(DSP)

디지털화된 사운드는 재생하는 동안 조작이 쉽다. 디지털 신호 처리 DSP(Digital Signal Processing)는 신호에 대한 연산 조작을 뜻한다. 볼륨을 조절하거나 신호의 피치를 조정하는 것은 DSP의 한 예다.
게임에서는 다음 2가지 일반적인 DSP 효과를 사용한다.

  • 리버브(reverb): 밀폐된 구역에서 소리가 튀는 현상
  • 이퀄라이제이션(equalization): 사운드 볼륨 레벨을 설정된 범위로 표준화시킨다.

버스(bus)

FMOD에서 각 사운드 이벤트는 자신만의 DSP 이펙트 체인을 가질 수도 있지만, 일반적으로 관리의 편의를 위해 여러 사운드 유형별로 그룹화하여 그룹별 DSP 이펙트 체인을 설정한다. 이러한 사운드의 그룹화를 버스(bus) 라고 한다. 많은 게임들은 카테고리별 사운드 볼륨 슬라이더를 제공한다. 이 기능은 버스를 사용하면 쉽게 구현할 수 있다.

FMOD에서 기본적으로 모든 프로젝트는 루트 경로가 bus:/.인 마스터 버스를 가진다. 때문에 bus:/.를 조작하면 모든 사운드 이벤트를 조정할 수 있다. 그리고 버스는 사운드 디자이너가 원하는 만큼 추가할 수도 있다.

사용자는 다음과 같이 bus를 활용하여 마스터 볼륨을 조절 할 수 있다.

// ... (생략) ...
    switch (key)
    {
    case '-':
    {
        // master volume 감소
        float volume = mAudioSystem->GetBusVolume("bus:/");
        volume = Math::Max(0.0f, volume - 0.1f);
        mAudioSystem->SetBusVolume("bus:/", volume);
        break;
    }
    case '=':
    {
        // master volume 증가
        float volume = mAudioSystem->GetBusVolume("bus:/");
        volume = Math::Min(1.0f, volume + 0.1f);
        mAudioSystem->SetBusVolume("bus:/", volume);
        break;
    }
// ... (생략)...

스냅샷(snapshot)

FMOD에서 스냅샷(snapshot)은 버스를 제어하는 특별한 유형의 이벤트다. 스냅샷도 이벤트이므로 같은 이벤트 인터페이스를 사용하며, 기존의 PlayEvent 함수에서도 스냅샷이 잘 동작한다. 유일한 차이는 스냅샷의 경로가 event:/. 대신 snapshot:/로 시작한다는 점이다.

차폐 (Sound Occlusion)

장애물을 통과해서 들려오는 소리는 장애물이 없을 때와 다르게 들린다. 이러한 현상을 차폐(Sound Occlusion)라고 한다. 아래 영상 FPS게임에서의 차폐현상 보여준다. 특히나 FPS게임에서 소리는 적의 위치를 추측하는 중요한 단서이기 때문에 매우 중요하게 작용한다.

▲FPS 게임속 차폐(Sound Occlusion)

일반적으로 차폐가 발생하면 고음이 저음보다 상대적으로 더 많이 차단된다. 그래서 차폐의 효과는 고주파 사운드의 볼륨을 줄이는 로우 패스 필터(low pass filter)가 적용된다.

▲ 소리의 차폐현상 (출처: Game Programming Algorithms and Techniques)

차폐를 구현하려면 2가지 별도의 작업이 필요하다.

  • 차폐의 감지
  • 차폐가 적용된 사운드의 수정

차폐의 감지에 대한 한 가지 방법은 소리의 진원지와 리스너 주변 원호 사이에 선분을 그리는 것이다. 모든 선분이 물체에 부딛침 없이 리스너에 도달할 수 있다면 차폐가 없다. 그리고 모든 선분이 리스너에 도달 할 수 없다면 완전한 차폐를 뜻한다.

차폐의 적용에는 저수준 API를 사용해야한다. 우선 FMOD 초기화할 때 소프트웨어 로우 패스 필터링을 활성화 한다.

result = mSystem->initialzie(
    512,    // 동시에 출력할 수 있는 사운드의 최대 수
    FMOD_STUDIO_INIT_NORMAL,    // 기본 세팅 사용
    FMOD_INIT_CHANNEL_LOWPASS,  // 로우 패스 필터 초기화
    nullptr // NULL
);

다음으로 차폐에 영향을 받는 각 이벤트 인스턴스에 차폐 파라미터를 설정한다.

// 채널 그룹을 사용할 수 있도록 커맨드를 비운다.
mSystem->flushCommands();
// 이벤트로부터 채널 그룹을 만든다.
FMOD::ChannelGroup* cg = nullptr;
event->getChannelGroup(&cg);
// 차폐 인자를 설정한다 - occFactor는 0.0 (차폐 없음)에서 1.0 (완전한 차폐) 값을 가진다.
cg->set3DOcclusion(occFactor, occFactor);

출처:

에이콘 출판 <Game Programming in C++>