버전

menu_open
Wwise SDK 2019.2.15
통합 세부 사항 - Event

소개

Event는 Wwise 사용자에 의해 생성되며, Wwise 오브젝트에서 수행할 동작을 지정합니다. 예를 들어, 한 이벤트 안에 Bird1 소리에 대한 Play 동작과 Bird2 소리에 대한 Stop 동작이 포함돼있는 식입니다. 그리고 또 다른 이벤트에는 CarEngine 소리에 상대적 음량의 상쇄값이 -2로 설정된 Set Volume 동작과, Ground_Material 스위치 그룹을 Tiles로 변경하는 Set Switch 동작이 포함돼있을 수도 있습니다.

그러면 게임 내에서 불러오는 SoundBank에 Event를 패키지해서 넣으면, 게임 코드가 이 이벤트들을 트리거하게 됩니다. 예를 들어, 플레이어가 부엌에 들어갈 때 Ground_Material 스위치를 Tiles로 변경하는 이벤트를 트리거하는 경우입니다.

} 게임이 동일한 이벤트를 트리거하므로, Wwise 사용자의 변경내용은 프로그래머의 추가 작업이나 코드의 재컴파일을 거치지 않아도 게임 내에서 즉시 시행됩니다.

게임에 이벤트 통합

AK::SoundEngine::PostEvent "PostEvent()" 함수는 수행할 Event의 대기 행렬을 만들거나, ID나 이름으로 이벤트를 식별할 때 사용합니다. 특정 이벤트를 트리거하고자 할 때 게임 코드로 이 함수를 호출합니다.

그러나 AK::SoundEngine::RenderAudio "RenderAudio()" 함수를 호출하기 전에는 어떤 이벤트도 트리거되지 않습니다. AK::SoundEngine::RenderAudio "RenderAudio()" 함수를 게임 프레임마다 한 번씩 호출하는 것이 이상적입니다.

AK::SoundEngine::RenderAudio "RenderAudio()"가 호출되면,

  • AK::SoundEngine::RenderAudio "RenderAudio()"가 마지막으로 호출된 이후 게시된 모든 이벤트를 처리합니다.
  • 그리고, 새로운 3D Position, 스위치, 스테이트 및 RTPC의 값을 사용할 수 있게 됩니다.

여러 이벤트가 있을 경우, 게임에 게시된 순서대로 처리됩니다. 이벤트 내 동작은 Wwise에서 보이는 순서대로 처리됩니다.

동일한 프레임 내 모든 이벤트는 최대한 한 번에 함께 처리됩니다. 단, 지연을 포함하고 있는 동작은 물론 나중에 수행됩니다.

어떤 이유로든 AK::SoundEngine::RenderAudio "RenderAudio()" 함수가 오랜 시간 동안 (서너 프레임 정도) 호출되지 않으면, 스트리밍 사운드는 정상적으로 재생되지만, 다음 AK::SoundEngine::RenderAudio "RenderAudio()"가 호출되기 전까지는 새로운 이벤트가 시작되거나 새로운 위치 지정이 적용되지 않습니다.

ID 사용 활성화

ID로 작업하기 위해서는 Wwise 내 Generate SoundBanks 대화 상자에서 반드시 "Generate header file" 옵션으로 뱅크를 생성해야 합니다. named Wwise_IDs.h 정의 파일은 필요한 모든 ID를 포함합니다. 이 파일은 각각의 뱅크가 생성될 때마다 갱신됩니다.

이벤트 알림

AK::SoundEngine::PostEvent "PostEvent()" 함수는, 마커에 도달했을 때나 이벤트가 종료됐을 때 호출되는 AkEventCallbackFunc() 함수를 가리키는 포인터를 받습니다. 이 기능은 이벤트와 소리 재생을 동기화시킬 때 매우 유용합니다.

모든 동작이 수행됐고, 이벤트로 트리거된 모든 사운드 재생이 끝나면 이 이벤트는 종료된 것으로 간주합니다. 스스로 종료하지 않는 이벤트도 있다는 점에 유의하세요. 예를 들어 무한으로 반복하는 사운드가 포함된 이벤트의 경우, 다른 이벤트로 이 사운드를 정지시켜야 콜백이 트리거됩니다.

마커는 SoundForge®나Adobe® Audition®과 같은 외부 wave 파일 편집기로 생성해야 합니다. 사운드 엔진은 이 큐 지점을 인식하고, AK::SoundEngine::PostEvent "PostEvent()"를 호출할 때 이를 지정했는지 콜백 함수에 알려줍니다.

참고

이벤트 게시와 실제 사운드 재생 사이 걸리는 지연 시간

이벤트가 게시되는 시점과 플랫폼이 오디오 데이터를 재생하기 시작하는 시점 사이의 지연 시간을 계산할 수 있습니다.

게임 스레드에서 SDK 함수 PostEvent()를 호출합니다. 이벤트를 게시하면 재생 요청을 게시하게 됩니다. 게임이 RenderAudio() 함수를 호출하기 전까지는 이 요청이 처리되지 않습니다. 즉, 오디오를 실제 렌더링하지는 않고 마지막 RenderAudio() 호출 이후 게시된 요청을 처리하라는 알림만 설정합니다. 일반적으로 RenderAudio()는 게임에 의해 게임 프레임 당 한 번씩 호출됩니다. 그러나 꼭 그렇게 정해진 것은 아닙니다. 언제든 호출해서 최근 게시된 이벤트를 곧바로 실행할 수도 있습니다.

RenderAudio()가 호출되면, 앞서 게시된 이벤트/명령을 소비하라는 승인이 오디오 (EventManager) 스레드에게 떨어집니다. 그러나 이 스레드는 플랫폼 오디오의 소비율과 동기화돼있다는 점을 기억하세요. "audio refill" 전달은 오디오 출력 모듈이 버퍼를 소비할 때에만 실행되어, 쓰기가 가능한 링 버퍼 영역을 만듭니다.

마지막으로 고려해야할 것은 출력 모듈의 링 버퍼 크기입니다. Windows에서 사운드 엔진을 초기화할 때, AkPlatformInitSettings::uNumRefillsInVoice 를 이용해 플랫폼별 매개 변수에 링 버퍼 크기를 지정할 수 있습니다. 이렇게 하면 보이스 버퍼 내 "refill buffer" 개수가 부여됩니다. 2는 이중 버퍼를 뜻하며 기본값은 4입니다. 여기서 정하는 숫자에 따라 지연 시간 단축과 (작은 버퍼) 메모리 고갈 (큰 버퍼) 사이 균형이 결정됩니다.

주로 호출되는 "refill buffer"나 "audio frame"는 주파수에 대한 샘플 레이트에 의해 결정됩니다. 따라서 고급 모드의 Windows에서는 일반적으로 (1,024 샘플) / (48,000 Hz) = 21.3 ms가 됩니다. 만약 AkInitSettings::uNumSamplesPerFrame를 이용해 샘플을 512로 설정하면 오디오 프레임은 (512 샘플) / (48,000 Hz) = 10.6 ms가 됩니다.

요약하자면, "전체 사운드 엔진의 지연 시간"은 다음 요인에 의해 결정됩니다.

  1. PostEvent() 호출과 RenderAudio() 호출 (게임에 따라 다를 수 있음) 사이의 시간. 즉, 예를 들어 매 프레임마다 RenderAudio()를 한 번씩 호출하는 초당 60 프레임의 게임에서는, 16 ms가 걸린다는 뜻입니다.
  2. RenderAudio()와 오디오 프레임 경계 사이의 시간. RenderAudio()가 현재 오디오 프레임의 시작에서 호출됐는지 끝에서 호출됐는지에 따라 0 에서 21 ms 사이에 결정됩니다.
  3. 출력 단계 버퍼링. 이중 버퍼 출력 단계에서는 2 * 21 ms = 42 ms의 지연 시간이 걸립니다.
    1. 오디오 프레임 레이트 오디오 프레임 레이트가 줄고 이중 버퍼 출력 단계의 경우, 2 * 11 ms = 22 ms의 지연 시간이 걸립니다.

다 합해서, 초당 60 프레임의 업데이트 시스템의 경우,

  • 최소 42 ms 지연 시간
  • 최대 79 ms 지연 시간

스트리밍

사운드가 100% 스트리밍되는 경우라면 (즉, 메모리에 적재되는 것이 없음), 위에서 설명한 사운드 엔진의 지연 시간 계산에 더해 고유의 I/O 지연 시간을 추가해야 합니다. I/O 지연 시간을 피하기 위해서는 Zero latency를 지정해 사운드의 시작 부분이 메모리에 로드되도록 합니다. 이 버퍼의 크기는 Prefetch length 에 의해 결정되며, 주로 안전하게 100 ms를 기본으로 설정해놓습니다.

이벤트 처리 예시

유용한 예시 (수도 코드):

PostEvent( Play_Sound1, GameObj_X )
PostEvent( Stop_Sound1, GameObj_X)
결과: 아무것도 재생되지 않음
PostEvent( Stop_Sound1, GameObj_X )
PostEvent( Play_Sound1, GameObj_X )
결과: Sound1이 재생됨
SetSwitch( Grass, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
SetSwitch( Concrete, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
결과: Grass와 Concrete 사운드 둘 다 재생됨
SetSwitch( Grass, GameObj_X )
SetSwitch( Concrete, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
결과: Concrete 사운드만 두 번 재생됨

이벤트 통합과 관련된 예시는 예제 통합으로 빠르게 시작하기 - 이벤트 를 참고해주세요.

AKSOUNDENGINE_API AKRESULT SetSwitch(AkSwitchGroupID in_switchGroup, AkSwitchStateID in_switchState, AkGameObjectID in_gameObjectID)
AKSOUNDENGINE_API AKRESULT RenderAudio(bool in_bAllowSyncRender=true)
AKSOUNDENGINE_API AkPlayingID PostEvent(AkUniqueID in_eventID, AkGameObjectID in_gameObjectID, AkUInt32 in_uFlags=0, AkCallbackFunc in_pfnCallback=NULL, void *in_pCookie=NULL, AkUInt32 in_cExternals=0, AkExternalSourceInfo *in_pExternalSources=NULL, AkPlayingID in_PlayingID=AK_INVALID_PLAYING_ID)

이 페이지가 도움이 되었나요?

지원이 필요하신가요?

질문이 있으신가요? 문제를 겪고 계신가요? 더 많은 정보가 필요하신가요? 저희에게 문의해주시면 도와드리겠습니다!

지원 페이지를 방문해 주세요

작업하는 프로젝트에 대해 알려주세요. 언제든지 도와드릴 준비가 되어 있습니다.

프로젝트를 등록하세요. 아무런 조건이나 의무 사항 없이 빠른 시작을 도와드리겠습니다.

Wwise를 시작해 보세요