버전
menu_open
Wwise SDK 2023.1.3
스피커 매트릭스 콜백을 이용한 고급 믹스 커스텀화

일부 게임은 라우팅 및 패닝과 관련해 매우 특정한 요구사항이 있는데, Wwise에서 준비된 기능이 없는 경우가 있습니다. 이를 위한 해결책으로 'speaker matrix callback'에 등록하는 방법이 있습니다. 보이스나 버스가 다른 버스로 믹싱되려고 할 때 이 콜백이 호출됩니다. 이 콜백에서 전역적 또는 특정 채널에 국한된 보이스나 버스 레벨을 변경할 수 있어, 믹스나 패닝을 수정할 수 있습니다.

다음 예제는 한 보이스에 대해 콜백을 등록하는 방법을 보여줍니다. 해당 보이스를 재생하는 이벤트를 발송할 때 이런 작업이 발생합니다.

AK::SoundEngine::PostEvent( AK::EVENTS::PLAY_HELLO, GAME_OBJECT_HUMAN, AK_SpeakerVolumeMatrix, VoiceCallback );

VoiceCallback 콜백은, 출력 버스를 구별해내는 방법, 보이스가 출력 버스에 믹싱돼 들어갈 때 기본 볼륨을 변경하는 방법, 그리고 패닝 볼륨을 변경해 다양한 입사각을 시뮬레이션하는 방법을 보여줍니다. AkSpeakerVolumeMatrixCallbackInfo::pContext 는 보이스와 관련 있는 정보를 나타내며, AkSpeakerVolumeMatrixCallbackInfo::pMixerContext 는 믹싱되는 버스와 관련된 정보를 나타냅니다 (dry 출력 버스, 또는 보조 센드).

static void VoiceCallback(
AkCallbackType in_eType, // Callback 타입.
AkCallbackInfo* in_pCallbackInfo // 필요한 정보가 담긴 구조체. 콜백 타입에 따라 올바른 하위 타입으로 캐스팅할 수 있습니다.
)
{
// 이것이 스피커 볼륨 매트릭스 콜백이라는 것을 알고 있습니다. 올바른 하위 타입으로 캐스팅합니다.
AkSpeakerVolumeMatrixCallbackInfo* pVolumeCallbackInfo = (AkSpeakerVolumeMatrixCallbackInfo*)in_pCallbackInfo;
// PostEvent()로 전달되거나 반환된 ID에 해당하는 이벤트 및 게임 오브젝트, 재생 ID.
AkUniqueID eventID = pVolumeCallbackInfo->eventID;
AkGameObjectID objID = pVolumeCallbackInfo->gameObjID;
AkPlayingID playingID = pVolumeCallbackInfo->playingID;
AKASSERT( eventID == AK::EVENTS::PLAY_HELLO );
// 이 콜백은 보이스가 라우팅되는 각 버스에 대해 호출됩니다. 이 예제에서는 믹스를 "My_Dry_Bus" 버스로만 커스텀하고자 합니다.
if ( pVolumeCallbackInfo->pMixerContext->GetBusID() != AK::SoundEngine::GetIDFromString( "My_Dry_Bus" ) )
return;
// "base" 볼륨에 임의로 변경사항을 적용합니다 (예: 모든 채널에 적용).
// ---------------------------------------------------------------------------------
// "My_Dry_Bus"에 보이스 볼륨을 두 배로 증가시킵니다 (+6dB).
*pVolumeCallbackInfo->pfBaseVolume *= 2.f;
// "My_Dry_Bus"에 대해 보이스의 거리 감쇠(distance attenuation)의 실행을 취소합니다 (단일 위치일 경우).
*pVolumeCallbackInfo->pfEmitterListenerVolume = 1.f;
// "My_Dry_Bus"에 대해 보이스 패닝을 변경합니다. 해당 사운드가 3D 위치 지정을 사용할 경우를 가정해봅시다.
// ---------------------------------------------------------------------------------
AkUInt32 uNumPosition = pVolumeCallbackInfo->pContext->GetNum3DPositions();
// 하나의 3D 사운드에는 여러 개의 위치가 있을 수 있습니다 (AK::SoundEngine::SetMultiplePositions() 참고). 이번 예제에서는 첫 번째 위치만 고려합니다.
if ( uNumPosition > 0 )
{
// 리스너 위치를 쿼리합니다. 일반적으로, 보이스가 믹싱되는 버스는 리스너에 따라 좌우됩니다. 따라서 게임 오브젝트를 믹서에 연결하세요.
AkTransform posListener;
AK::IAkGameObjectPluginInfo * pBusObject = pVolumeCallbackInfo->pMixerContext->GetGameObjectInfo();
if (pBusObject)
{
pBusObject->GetGameObjectPosition(0, posListener);
// 재미 삼아 리스너를 뒤집어봅시다.
AkVector listenerTop = posListener.OrientationTop();
listenerTop.X = -listenerTop.X;
listenerTop.Y = -listenerTop.Y;
listenerTop.Z = -listenerTop.Z;
posListener.SetOrientation(posListener.OrientationFront(), listenerTop);
// 이미터 게임 오브젝트 위치를 구합니다.
AkTransform posEmitter;
pVolumeCallbackInfo->pContext->GetVoiceInfo()->GetGameObjectPosition(0, posEmitter);
// 버스나 믹서의 믹싱을 이용해 새로운 패닝 볼륨을 계산하세요.
pVolumeCallbackInfo->pMixerContext->Compute3DPositioning(
posEmitter, // 이미터 트랜스폼.
posListener, // 리스너 트랜스폼.
pVolumeCallbackInfo->pContext->GetCenterPerc(), // 중앙 비율. 중앙이 있는 출력의 모노 입력에만 적용합니다.
pVolumeCallbackInfo->pContext->GetSpread(0), // 확산.
pVolumeCallbackInfo->pContext->GetFocus(0), // 포커스.
pVolumeCallbackInfo->inputConfig, // 입력의 채널 구성.
pVolumeCallbackInfo->inputConfig.uChannelMask, // 패닝에 선택된 채널의 마스크 (제외된 입력 채널은 해당 출력에 영향을 주지 않습니다).
pVolumeCallbackInfo->outputConfig, // 원하는 출력 구성.
pVolumeCallbackInfo->pVolumes // 반환된 볼륨 매트릭스. AK::SpeakerVolumes::Matrix::GetRequiredSize() 를 이용해 사전 할당되어야 합니다 ( AK::SpeakerVolumes::Matrix services 참고).
);
}
}
}

다음 예제는 버스 콜백을 등록하는 방법입니다. 여기서는 AkSpeakerVolumeMatrixCallbackInfo::pContext 가 ("My_Bus")로 등록한 버스와 관련된 정보를 나타내며, AkSpeakerVolumeMatrixCallbackInfo::pMixerContext 는 믹싱되는 버스, 상위 버스와 관련된 정보를 나타냅니다 (또는 시그널 체인에서 다음 믹싱 버스 관련 정보를 나타냅니다).

static void BusCallback(
AkSpeakerVolumeMatrixCallbackInfo* in_pCallbackInfo // 필요한 버스 정보가 들어있는 구조체.
)
{
// 버스로부터 호출됨: 재생 ID와 연결 불가능.
AKASSERT( in_pCallbackInfo->playingID == AK_INVALID_PLAYING_ID );
// 상위 버스로 믹싱되기 전에 해당 버스의 출력 지점에서 믹스다운 신호의 패닝 볼륨을 변경합니다.
// 믹싱 서비스를 이용하여 입력을 3-스테레오 구성으로 Transmix하고, 상위 버스의 다른 모든 채널에 끼치는 영향을 없앱니다.
// Transmix 게인을 얻기 위해 볼륨 매트릭스를 할당합니다 (input_config -> 3-stereo).
AkChannelConfig cfgThreeStereo;
in_pCallbackInfo->inputConfig, // 입력의 채널 구성.
cfgThreeStereo, // 믹성 출력의 채널 구성.
in_pCallbackInfo->pContext->GetCenterPerc(),// Center%: Wwise가 계산한 center% 값을 사용.
mxTransmix );
// 가능하면 결과를 실제 믹싱 매트릭스로 복사하고 후방 채널과 LFE를 정리.
// 주의: 믹싱 버스에 중앙 채널이 있는지 알 수 없으므로 확인이 필요함.
AkChannelConfig cfgThreeStereoANDBus;
cfgThreeStereoANDBus.SetStandard( AK_SPEAKER_SETUP_3STEREO & in_pCallbackInfo->outputConfig.uChannelMask );
AkUInt32 uNumOutputChannelsToCopy = cfgThreeStereoANDBus.uNumChannels;
for ( AkUInt32 uChanIn = 0; uChanIn < in_pCallbackInfo->inputConfig.uNumChannels; uChanIn++ )
{
// 각각의 입력 채널에 대해 출력 볼륨 벡터를 구함.
AK::SpeakerVolumes::VectorPtr vTransmixOut = AK::SpeakerVolumes::Matrix::GetChannel( mxTransmix, uChanIn, cfgThreeStereo.uNumChannels );
// 앞 채널로 패닝 복사.
AkUInt32 uChanOut = 0;
while ( uChanOut < uNumOutputChannelsToCopy )
{
vMixOut[uChanOut] = vTransmixOut[uChanOut];
++uChanOut;
}
// 다른 채널 정리.
while ( uChanOut < in_pCallbackInfo->outputConfig.uNumChannels )
{
vMixOut[uChanOut] = 0;
++uChanOut;
}
}
}

다음 예제는 버스에 등록해 미터링 데이터를 쿼리하는 방법을 보여줍니다.

// 버스 미터링에 등록. 참고: 미터링에 등록하는 방법은 비용이 매우 높은 편이며, 특히 True Peak와 K-Weighted Power가 높습니다.
static void MeterCallback(
AK::AkMetering * in_pMetering, // AK::AkMetering struct containing metering information.
AkChannelConfig in_channelConfig, // 버스의 채널 구성.
AkMeteringFlags in_eMeteringFlags // RegisterBusMeteringCallback() 에서 요청된 미터링 플래그. in_pMeteringInfo 로 해당하는 미터 값에만 접근할 수 있습니다. 다른 접근은 실패합니다.
)
{
// 콜백을 등록했기 때문에 최소한 True Peak와 K-Weighted Power 미터링이 활성화돼있어야 합니다.
AKASSERT( ( in_eMeteringFlags & AK_EnableBusMeter_TruePeak ) && ( in_eMeteringFlags & AK_EnableBusMeter_KPower ) );
// K-Weighted Power를 구해 작업을 수행합니다.
AkReal32 fPower = in_pMetering->GetKWeightedPower();
// True Peak를 구해 작업을 수행합니다.
// 채널당 하나의 값이 있습니다.
AK::SpeakerVolumes::ConstVectorPtr vTruePeak = in_pMetering->GetTruePeak();
for ( AkUInt32 uChannel = 0; uChannel < in_channelConfig.uNumChannels; uChannel++ )
{
AkReal32 fChannelPeak = vTruePeak[uChannel];
...
}
...
}
AkGameObjectID gameObjID
Game object ID
Definition: AkCallback.h:87
AkReal32 * pfBaseVolume
Base volume, common to all channels.
Definition: AkCallback.h:168
@ AK_EnableBusMeter_KPower
Enable computation of K-weighted power metering (used as a basis for computing loudness,...
Definition: AkTypes.h:1241
AkChannelConfig outputConfig
Channel configuration of the output bus.
Definition: AkCallback.h:167
AKSOUNDENGINE_API AKRESULT RegisterBusVolumeCallback(AkUniqueID in_busID, AkBusCallbackFunc in_pfnCallback, void *in_pCookie=NULL)
AkUInt32 uNumChannels
Number of channels.
AkChannelConfig inputConfig
Channel configuration of the voice/bus.
Definition: AkCallback.h:166
AkUInt64 AkGameObjectID
Game object ID
Definition: AkTypes.h:142
const AkVector & OrientationFront() const
Get orientation front vector.
Definition: AkTypes.h:626
const AkVector & OrientationTop() const
Get orientation top vector.
Definition: AkTypes.h:632
AkUInt32 uChannelMask
Channel mask (configuration).
AkMeteringFlags
Metering flags. Used for specifying bus metering, through AK::SoundEngine::RegisterBusVolumeCallback(...
Definition: AkTypes.h:1235
AkForceInline AkUInt32 GetRequiredSize(AkUInt32 in_uNumChannelsIn, AkUInt32 in_uNumChannelsOut)
Compute size (in bytes) required for given channel configurations.
AK::IAkMixerPluginContext * pMixerContext
Output mixing bus context. Use it to access a few useful panning and mixing services,...
Definition: AkCallback.h:170
AkCallbackType
Type of callback. Used as a bitfield in methods AK::SoundEngine::PostEvent() and AK::SoundEngine::Dyn...
Definition: AkCallback.h:48
float AkReal32
32-bit floating point
virtual AKRESULT GetGameObjectPosition(AkUInt32 in_uIndex, AkSoundPosition &out_position) const =0
AkUniqueID eventID
Unique ID of Event, passed to PostEvent()
Definition: AkCallback.h:97
AkReal32 * VectorPtr
Volume vector. Access each element with the standard bracket [] operator.
AkReal32 Y
Y Position
Definition: AkTypes.h:487
AkUInt32 AkUniqueID
Unique 32-bit ID
Definition: AkTypes.h:134
AkReal32 X
X Position
Definition: AkTypes.h:486
AkForceInline VectorPtr GetChannel(MatrixPtr in_pVolumeMx, AkUInt32 in_uIdxChannelIn, AkUInt32 in_uNumChannelsOut)
Get pointer to volume distribution for input channel in_uIdxChannelIn.
@ AK_EnableBusMeter_TruePeak
Enable computation of true peak metering (most CPU and memory intensive).
Definition: AkTypes.h:1238
#define AK_SPEAKER_SETUP_3STEREO
3.0 setup channel mask
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AkAlloca(_size_)
Stack allocations.
AkReal32 Z
Z Position
Definition: AkTypes.h:488
void SetOrientation(const AkVector &in_orientationFront, const AkVector &in_orientationTop)
Set orientation. Orientation front and top should be orthogonal and normalized.
Definition: AkTypes.h:698
AKSOUNDENGINE_API AKRESULT RegisterBusMeteringCallback(AkUniqueID in_busID, AkBusMeteringCallbackFunc in_pfnCallback, AkMeteringFlags in_eMeteringFlags, void *in_pCookie=NULL)
AkReal32 * pfEmitterListenerVolume
Emitter-listener pair-specific gain. When there are multiple emitter-listener pairs,...
Definition: AkCallback.h:169
virtual AKRESULT Compute3DPositioning(AkReal32 in_fAngle, AkReal32 in_fElevation, AkReal32 in_fSpread, AkReal32 in_fFocus, AkChannelConfig in_inputConfig, AkChannelMask in_uInputChanSel, AkChannelConfig in_outputConfig, AkReal32 in_fCenterPerc, AK::SpeakerVolumes::MatrixPtr out_mxVolumes)=0
Struct containing metering information about a buffer. Depending on when this struct is generated,...
Definition: AkCommonDefs.h:204
static const AkPlayingID AK_INVALID_PLAYING_ID
Invalid playing ID
Definition: AkTypes.h:179
virtual AKRESULT ComputeSpeakerVolumesDirect(AkChannelConfig in_inputConfig, AkChannelConfig in_outputConfig, AkReal32 in_fCenterPerc, AK::SpeakerVolumes::MatrixPtr out_mxVolumes)=0
AKSOUNDENGINE_API AkUInt32 GetIDFromString(const char *in_pszString)
virtual IAkGameObjectPluginInfo * GetGameObjectInfo()=0
AkForceInline void SetStandard(AkUInt32 in_uChannelMask)
Set channel config as a standard configuration specified with given channel mask.
AkReal32 * MatrixPtr
Volume matrix. Access each input channel vector with AK::SpeakerVolumes::Matrix::GetChannel().
uint32_t AkUInt32
Unsigned 32-bit integer
Game object information available to plugins.
Definition: IAkPlugin.h:102
3D vector for some operations in 3D space. Typically intended only for localized calculations due to ...
Definition: AkTypes.h:444
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)
@ AK_SpeakerVolumeMatrix
Callback triggered at each frame, letting the client modify the speaker volume matrix....
Definition: AkCallback.h:54
AK::SpeakerVolumes::MatrixPtr pVolumes
Pointer to volume matrix describing the contribution of each source channel to destination channels....
Definition: AkCallback.h:165
Position and orientation of objects in a "local" space
Definition: AkTypes.h:613
AkUInt32 AkPlayingID
Playing ID
Definition: AkTypes.h:137
AkPlayingID playingID
Playing ID of Event, returned by PostEvent()
Definition: AkCallback.h:96
const AkReal32 * ConstVectorPtr
Constant volume vector. Access each element with the standard bracket [] operator.

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

지원이 필요하신가요?

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

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

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

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

Wwise를 시작해 보세요