You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- 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]
236 lines
6.3 KiB
C++
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);
|
|
}
|