バージョン
menu_open
警告:あなたのメジャーリリース ( 2021.1.14.8108 ) に該当する最新ドキュメンテーションが表示されています。特定バージョンのドキュメンテーションにアクセスするには、Audiokinetic Launcherでオフラインドキュメンテーションをダウンロードし、Wwise AuthoringのOffline Documentationオプションにチェックを入れてください。
Wwise Unreal Integration Documentation
Audio Input

Wwise Audio Inputプラグイン

Unrealインテグレーションは、Wwise Audio Inputプラグイン経由で、Wwiseにオーディオ入力の方法を提供します。Audio Input Source Plug-in from the Wwise SDK documentationを参照してください。Wwiseにオーディオ入力を提供するには、クラスを AkAudioInputComponent から継承します。

AkAudioInputComponent

AkAudioInputComponent は、 AkComponent から派生しています。特別な AkComponent で、Wwiseにオーディオ入力を提供するために使えます。2つの主要な関数を、実装する必要があります。

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

また、 Post Associated Audio Input Event というブループリント関数も1つあり、コンポーネントのAkAudioEventを、関連するAudioSamplesコールバックやAudioFormatコールバックと共にWwiseにポストするために、ゲームオブジェクトソースとしてこのコンポーネントを使います。

Custom Audio Inputの動作

カスタマイズしたオーディオ入力の動作を実装するために、AkAudioInputComponentから派生したカスタムクラスを書くことができます。以下の、 UAkVoiceInputComponent.h と UAkVoiceInputComponent.cpp の例は、マイクロフォンの入力をWwiseサウンドエンジンに送るクラスを表しています。

これらのファイルをC++ Unrealプロジェクトで使うには、初期設定が必要です。まずAkAudioとUnreal Voiceの両方のモジュールを互いにリンクさせる必要があるので、以下の例のように、プロジェクトのBuild.csファイルの、PublicDependencyModuleNamesに、これらを追加します。

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

次に、Voiceモジュールの bEnabled フラグをTrueに設定する必要があるので、以下のラインをDefaultEngine.iniファイルに追加します:

[Voice]
bEnabled=true

この初期設定が終われば、マイクロフォン入力をWwiseに送信する、カスタマイズされたオーディオ入力の動作を示す以下のクラスを、追加することができます。

このコードは、簡単で短い例を提供するためにここで使われています。出荷するゲームで使うものではありません!

AkVoiceInputComponent.h:

#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;
};

AkVoiceInputComponent.cpp:

#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();
}
}

このクラスをUnrealプロジェクトに追加すると、 AkVoiceInputComponent のあるカスタムブループリントクラスを作成することができ、 Post Associated Audio Input Event ブループリント関数(ベースクラス AkAudioInputComponent から)をコールして、Wwiseにマイクロフォンデータの送信を開始できます。以下のイメージ図は、 Actor に基づくカスタムBlueprintクラスのBlueprintの一部で、 AkVoiceInput と呼ばれる AkVoiceInputComponent があります。


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

サポートは必要ですか?

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

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

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

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

Wwiseからはじめよう