You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb aaron.mcleran
https://p4-swarm.epicgames.net/reviews/6345090
#ROBOMERGE-SOURCE: CL 6399748 via CL 6400508
[CL 6400529 by rob gay in Main branch]
241 lines
6.3 KiB
C++
241 lines
6.3 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Audio includes.
|
|
------------------------------------------------------------------------------------*/
|
|
|
|
#include "AndroidAudioDevice.h"
|
|
#include "VorbisAudioInfo.h"
|
|
#include "ADPCMAudioInfo.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogAndroidAudio);
|
|
|
|
|
|
class FSLESAudioDeviceModule : public IAudioDeviceModule
|
|
{
|
|
public:
|
|
|
|
/** Creates a new instance of the audio device implemented by the module. */
|
|
virtual FAudioDevice* CreateAudioDevice() override
|
|
{
|
|
return new FSLESAudioDevice;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_MODULE(FSLESAudioDeviceModule, AndroidAudio );
|
|
|
|
|
|
DEFINE_STAT(STAT_AudioAndroidSourcePlayerCreateTime);
|
|
DEFINE_STAT(STAT_AudioAndroidSourcePlayerRealize);
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
UALAudioDevice constructor and UObject interface.
|
|
------------------------------------------------------------------------------------*/
|
|
|
|
void FSLESAudioDevice::Teardown( void )
|
|
{
|
|
// Flush stops all sources and deletes all buffers so sources can be safely deleted below.
|
|
Flush( NULL );
|
|
|
|
// Destroy all sound sources
|
|
for( int32 i = 0; i < Sources.Num(); i++ )
|
|
{
|
|
delete Sources[ i ];
|
|
}
|
|
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT("OpenSLES Tearing Down HW"));
|
|
|
|
// Teardown OpenSLES..
|
|
// Destroy the SLES objects in reverse order of creation:
|
|
if (SL_OutputMixObject)
|
|
{
|
|
(*SL_OutputMixObject)->Destroy(SL_OutputMixObject);
|
|
SL_OutputMixObject = NULL;
|
|
}
|
|
if (SL_EngineObject)
|
|
{
|
|
(*SL_EngineObject)->Destroy(SL_EngineObject);
|
|
SL_EngineObject = NULL;
|
|
SL_EngineEngine = NULL;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
UAudioDevice Interface.
|
|
------------------------------------------------------------------------------------*/
|
|
/**
|
|
* Initializes the audio device and creates sources.
|
|
*
|
|
* @warning:
|
|
*
|
|
* @return TRUE if initialization was successful, FALSE otherwise
|
|
*/
|
|
bool FSLESAudioDevice::InitializeHardware( void )
|
|
{
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT("SL Entered Init HW"));
|
|
|
|
SLresult result;
|
|
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT("OpenSLES Initializing HW"));
|
|
|
|
SLEngineOption EngineOption[] = { {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE} };
|
|
|
|
// create engine
|
|
result = slCreateEngine( &SL_EngineObject, 1, EngineOption, 0, NULL, NULL);
|
|
//check(SL_RESULT_SUCCESS == result);
|
|
if (SL_RESULT_SUCCESS != result)
|
|
{
|
|
UE_LOG( LogAndroidAudio, Error, TEXT("Engine create failed %d"), int32(result));
|
|
}
|
|
|
|
// realize the engine
|
|
result = (*SL_EngineObject)->Realize(SL_EngineObject, SL_BOOLEAN_FALSE);
|
|
check(SL_RESULT_SUCCESS == result);
|
|
|
|
// get the engine interface, which is needed in order to create other objects
|
|
result = (*SL_EngineObject)->GetInterface(SL_EngineObject, SL_IID_ENGINE, &SL_EngineEngine);
|
|
check(SL_RESULT_SUCCESS == result);
|
|
|
|
// create output mix, with environmental reverb specified as a non-required interface
|
|
result = (*SL_EngineEngine)->CreateOutputMix( SL_EngineEngine, &SL_OutputMixObject, 0, NULL, NULL );
|
|
check(SL_RESULT_SUCCESS == result);
|
|
|
|
// realize the output mix
|
|
result = (*SL_OutputMixObject)->Realize(SL_OutputMixObject, SL_BOOLEAN_FALSE);
|
|
check(SL_RESULT_SUCCESS == result);
|
|
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT("OpenSLES Initialized"));
|
|
// ignore unsuccessful result codes for env
|
|
|
|
|
|
// Default to sensible channel count.
|
|
if( MaxChannels < 1 )
|
|
{
|
|
MaxChannels = 12;
|
|
}
|
|
|
|
|
|
// Initialize channels.
|
|
for( int32 i = 0; i < FMath::Min( MaxChannels, 12 ); i++ )
|
|
{
|
|
FSLESSoundSource* Source = new FSLESSoundSource( this );
|
|
Sources.Add( Source );
|
|
FreeSources.Add( Source );
|
|
}
|
|
|
|
if( Sources.Num() < 1 )
|
|
{
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT( "OpenSLAudio: couldn't allocate any sources" ) );
|
|
return false;
|
|
}
|
|
|
|
// Update MaxChannels in case we couldn't create enough sources.
|
|
MaxChannels = Sources.Num();
|
|
UE_LOG( LogAndroidAudio, Warning, TEXT( "OpenSLAudioDevice: Allocated %i sources" ), MaxChannels );
|
|
|
|
// Set up a default (nop) effects manager
|
|
Effects = new FAudioEffectsManager( this );
|
|
|
|
return true;
|
|
}
|
|
|
|
FSoundSource* FSLESAudioDevice::CreateSoundSource()
|
|
{
|
|
return new FSLESSoundSource(this);
|
|
}
|
|
|
|
bool FSLESAudioDevice::HasCompressedAudioInfoClass(USoundWave* SoundWave)
|
|
{
|
|
#if WITH_OGGVORBIS
|
|
if(SoundWave->bStreaming)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static FName NAME_OGG(TEXT("OGG"));
|
|
if (SoundWave->HasCompressedData(NAME_OGG))
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
if(SoundWave->bStreaming)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static FName NAME_ADPCM(TEXT("ADPCM"));
|
|
if (SoundWave->HasCompressedData(NAME_ADPCM))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
class ICompressedAudioInfo* FSLESAudioDevice::CreateCompressedAudioInfo(USoundWave* SoundWave)
|
|
{
|
|
if (SoundWave->IsSeekableStreaming())
|
|
{
|
|
return new FADPCMAudioInfo();
|
|
}
|
|
|
|
#if WITH_OGGVORBIS
|
|
static FName NAME_OGG(TEXT("OGG"));
|
|
if (SoundWave->bStreaming || SoundWave->HasCompressedData(NAME_OGG))
|
|
{
|
|
return new FVorbisAudioInfo();
|
|
}
|
|
#endif
|
|
static FName NAME_ADPCM(TEXT("ADPCM"));
|
|
if (SoundWave->bStreaming || SoundWave->HasCompressedData(NAME_ADPCM))
|
|
{
|
|
return new FADPCMAudioInfo();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
FAudioPlatformSettings FSLESAudioDevice::GetPlatformSettings() const
|
|
{
|
|
return FAudioPlatformSettings::GetPlatformSettings(TEXT("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings"));
|
|
}
|
|
|
|
/** Check if any background music or sound is playing through the audio device */
|
|
bool FSLESAudioDevice::IsExernalBackgroundSoundActive()
|
|
{
|
|
#if USE_ANDROID_JNI
|
|
extern bool AndroidThunkCpp_IsMusicActive();
|
|
return AndroidThunkCpp_IsMusicActive();
|
|
#else
|
|
return false;
|
|
#endif
|
|
|
|
}
|
|
|
|
FAndroidSoundBufferNotification& FAndroidSoundBufferNotification::Get()
|
|
{
|
|
static FAndroidSoundBufferNotification Instance;
|
|
return Instance;
|
|
}
|
|
|
|
FDelegateHandle FAndroidSoundBufferNotification::AddDelegate(const FOnAndroidSoundBufferEnqueued::FDelegate& InNewDelegate)
|
|
{
|
|
FScopeLock Lock(&DelegateLock);
|
|
return InternalDelegate.Add(InNewDelegate);
|
|
}
|
|
|
|
void FAndroidSoundBufferNotification::RemoveDelegate(const FDelegateHandle& Handle)
|
|
{
|
|
FScopeLock Lock(&DelegateLock);
|
|
InternalDelegate.Remove(Handle);
|
|
}
|
|
|
|
void FAndroidSoundBufferNotification::Broadcast(const void* AudioData, int32 DataSize, int32 SampleRate, int32 NumChannels)
|
|
{
|
|
FScopeLock Lock(&DelegateLock);
|
|
InternalDelegate.Broadcast(AudioData, DataSize, SampleRate, NumChannels);
|
|
}
|