Files
UnrealEngineUWP/Engine/Source/Runtime/Android/AndroidAudio/Private/AndroidAudioDevice.cpp
rob gay ac2843522a - Simplify max channel count code by removing GEngineIni look-up for value set in Engine-level ini and just directly setting in UAudioSettings constructor
- Fix bug with IOS & XAudio2 old backends not respecting platform settings code/ini settings
- Move AudioDevice to override quality settings MaxChannels by ANY platform setting, on init, not just the minimal value.  This is okay on init as the source array has yet to be initialized.

https://p4-swarm.epicgames.net/reviews/6260062

#rb ethan.geller
#rb phil.popp

#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: rob.gay
#ROBOMERGE-SOURCE: CL 6345170 via CL 6346183 via CL 6346278
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)

[CL 6357483 by rob gay in Dev-VR branch]
2019-05-07 21:10:37 -04:00

236 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 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);
}