バージョン
menu_open
Wwise Unreal Integration Documentation
Providing Audio Input to Wwise

The Unreal integration provides audio input to Wwise through the Wwise Audio Input Source Plug-in. In order to provide audio input to Wwise, classes must inherit from AkAudioInputComponent.

AkAudioInputComponent

AkAudioInputComponent は、 AkComponent から派生しています。It is a specialized AkComponent that you can use to provide audio input to Wwise. To do so, you must implement two key functions:

/* オーディオコールバック。Wwiseサウンドエンジンがこれを継続的にコールし、
* サウンドエンジンにオーディオサンプルを提供するために使います。*/
virtual bool FillSamplesBuffer(uint32 NumChannels, uint32 NumSamples, float** BufferToFill);
/* このコールバックは、Wwiseサウンドエンジンに、必要なオーディオフォーマットを提供するために使います。*/
virtual void GetChannelConfig(AkAudioFormat& AudioFormat);

AkAudioInputComponent also has one Blueprint function, Post Associated Audio Input Event, which posts the component's AkAudioEvent to Wwise along with the associated AudioSamples callback and AudioFormat callback, using this component as the game object source.

Customizing Audio Input Behavior

You can write custom classes that derive from AkAudioInputComponent in order to implement custom audio input behavior. The following UAkVoiceInputComponent.h and UAkVoiceInputComponent.cpp examples show a class that takes microphone input and pipes it to the Wwise Sound Engine.

Before you can use these files in a C++ Unreal project, you must perform some initial setup. First, add the AkAudio and the Unreal Voice modules to the PublicDependencyModuleNames in the project's Build.cs file. 例:

public class MyModule : ModuleRules
{
public MyModule(ReadOnlyTargetRules Target) : base(Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AkAudio", "Voice" });
// その他の設定
}
}

Next, add the following lines to the DefaultEngine.ini file:

[Voice]
bEnabled=true

After these setup steps are complete, add the desired custom behavior. In the following example, a class takes microphone input and sends it to Wwise.

注記: The sample code in this section is not intended for use in shipped games. It is only a short example of how to implement custom behavior.

Here is an example of a customized AkVoiceInputComponent.h file:

#pragma once
#include "CoreMinimal.h"
#include "AkAudioInputComponent.h"
#include "Voice.h"
#include "AkVoiceInputComponent.generated.h"
/*
*/
UCLASS(ClassGroup = Audiokinetic, BlueprintType, hidecategories = (Transform, Rendering, Mobility, LOD, Component, Activation), meta = (BlueprintSpawnableComponent))
class WWISEDEMOGAME_API UAkVoiceInputComponent : public UAkAudioInputComponent
{
GENERATED_BODY()
UAkVoiceInputComponent(const class FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
protected:
/* これをコールするのは、このコンポーネントのオーナーであるGameObjectが、Wwiseサウンドエンジンから登録解除されたあとです。*/
virtual void PostUnregisterGameObject() override;
/* オーディオコールバック。これはWwiseサウンドエンジンが継続的にコールされ、
サウンドエンジンにオーディオサンプルを提供するために使います。*/
virtual bool FillSamplesBuffer(uint32 NumChannels, uint32 NumSamples, float** BufferToFill) override;
/* このコールバックは、Wwiseサウンドエンジンに、必要なオーディオフォーマットを提供するために使います。*/
virtual void GetChannelConfig(AkAudioFormat& AudioFormat) override;
/* マイクロフォン入力にアクセスするために使う、Unreal IVoiceCapture。*/
TSharedPtr<IVoiceCapture> VoiceCapture;
/* ボイスキャプチャーから新しいバッファが入る度に、このアレイがリセットされ、リフィルされます。*/
TArray<uint8> IncomingRawVoiceData;
/* このアレイに、今までボイスキャプチャで収集されたオーディオデータが、すべて入っています。
マイクロフォンデータがある場合に、それを処理する時にここに書き込み、
Wwiseエンジンにデータを渡すときに、ここから読み込み(そして縮小)します。
オーディオコールバック内でバッファを縮小することは推奨されないので、絶対にこれを出荷用のゲームに使わないでください! */
TArray<uint8> CollectedRawVoiceData;
/* このフラグは、収集したデータバッファから読み込んでいる最中に、マイクロフォンデータをここに書き込んでしまうのを防止するために使います。*/
FThreadSafeBool bIsReadingVoiceData = false;
};

Here is an example of a customized AkVoiceInputComponent.cpp file:

#include "AkVoiceInputComponent.h"
UAkVoiceInputComponent::UAkVoiceInputComponent(const class FObjectInitializer& ObjectInitializer) :
UAkAudioInputComponent(ObjectInitializer)
{
CollectedRawVoiceData.Reset();
VoiceCapture = FVoiceModule::Get().CreateVoiceCapture();
}
void UAkVoiceInputComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!VoiceCapture.IsValid())
{
return;
}
uint32 NumAvailableVoiceCaptureBytes = 0;
EVoiceCaptureState::Type CaptureState = VoiceCapture->GetCaptureState(NumAvailableVoiceCaptureBytes);
/* IVoiceCaptureが、ティックごとに、そのEVoiceCaptureStateを更新します。
このためティックの間は、収集すべき新しいデータがあるかどうかをステートが教えてくれることが、分かります。*/
if (CaptureState == EVoiceCaptureState::Ok && NumAvailableVoiceCaptureBytes > 0)
{
uint32 NumVoiceCaptureBytesReturned = 0;
IncomingRawVoiceData.Reset((int32)NumAvailableVoiceCaptureBytes);
IncomingRawVoiceData.AddDefaulted(NumAvailableVoiceCaptureBytes);
uint64 SampleCounter = 0;
VoiceCapture->GetVoiceData(IncomingRawVoiceData.GetData(), NumAvailableVoiceCaptureBytes, NumVoiceCaptureBytesReturned, SampleCounter);
if (NumVoiceCaptureBytesReturned > 0)
{
/* 収集バッファからデータを読み込む間は、スピンします。 */
while (bIsReadingVoiceData) {}
CollectedRawVoiceData.Append(IncomingRawVoiceData);
}
}
}
bool UAkVoiceInputComponent::FillSamplesBuffer(uint32 NumChannels, uint32 NumSamples, float** BufferToFill)
{
if (!VoiceCapture.IsValid())
{
return false;
}
const uint8 NumBytesPerSample = 2;
const uint32 NumRequiredBytesPerChannel = NumSamples * NumBytesPerSample;
const uint32 NumRequiredBytes = NumRequiredBytesPerChannel * NumChannels;
int16 VoiceSample = 0;
uint32 RawChannelIndex = 0;
uint32 RawSampleIndex = 0;
bIsReadingVoiceData = true;
const int32 NumSamplesAvailable = CollectedRawVoiceData.Num() / NumBytesPerSample;
const uint32 BufferSlack = (uint32)FMath::Max(0, (int32)(NumSamples * NumChannels) - NumSamplesAvailable);
for (uint32 c = 0; c < NumChannels; ++c)
{
RawChannelIndex = c * NumRequiredBytesPerChannel;
for (uint32 s = 0; s < NumSamples; ++s)
{
if (s >= (NumSamples - BufferSlack) / NumChannels)
{
/* Wwiseエンジンに必要なデータよりボイスキャプチャで受け取るデータの方が少ない場合は、
不足サンプルを0パディングします。*/
BufferToFill[c][s] = 0.0f;
}
else
{
/* 入ってくるマイクロフォンオーディオデータを、サイン済み浮動小数点に変換します。*/
uint32 RawSampleDataMSBIndex = s * 2 + 1;
uint32 RawSampleDataLSBIndex = s * 2;
VoiceSample = (CollectedRawVoiceData[RawSampleDataMSBIndex] << 8) | CollectedRawVoiceData[RawSampleDataLSBIndex];
BufferToFill[c][s] = VoiceSample / (float)INT16_MAX;
}
}
}
const int32 NumBytesRead = (NumSamples - BufferSlack) * NumBytesPerSample;
/* NOTE: オーディオコールバック内でバッファを縮小することは、推奨されません。出荷したゲームでは、これを絶対に使わないでください!*/
CollectedRawVoiceData.RemoveAt(0, NumBytesRead);
bIsReadingVoiceData = false;
return true;
}
void UAkVoiceInputComponent::GetChannelConfig(AkAudioFormat& AudioFormat)
{
const int sampleRate = 16000;
AudioFormat.uSampleRate = sampleRate;
AudioFormat.channelConfig.SetStandard(AK_SPEAKER_SETUP_MONO);
if (VoiceCapture.IsValid())
{
/* Passは、デフォルトデバイスを使うための空のデバイス名です。*/
if (!VoiceCapture->Init(FString(""), AudioFormat.uSampleRate, AudioFormat.channelConfig.uNumChannels))
{
UE_LOG(LogTemp, Error, TEXT("Failed to initialize device for voice input!"));
return;
}
VoiceCapture->Start();
}
}
void UAkVoiceInputComponent::PostUnregisterGameObject()
{
Super::PostUnregisterGameObject();
if (VoiceCapture.IsValid())
{
VoiceCapture->Stop();
VoiceCapture->Shutdown();
}
}

After you add the class to an Unreal project, you can create a custom Blueprint class that has an AkVoiceInputComponent, and can call the Post Associated Audio Input Event Blueprint function (from base class AkAudioInputComponent) to start sending microphone data to Wwise. The following image shows part of the Blueprint for a custom Blueprint class, based on Actor, that has an AkVoiceInputComponent called AkVoiceInput.


このページはお役に立ちましたか?

サポートは必要ですか?

ご質問や問題、ご不明点はございますか?お気軽にお問い合わせください。

サポートページをご確認ください

あなたのプロジェクトについて教えてください。ご不明な点はありませんか。

プロジェクトを登録していただくことで、ご利用開始のサポートをいたします。

Wwiseからはじめよう