123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /*******************************************************************************
- The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
- Technology released in source code form as part of the game integration package.
- The content of this file may not be used without valid licenses to the
- AUDIOKINETIC Wwise Technology.
- Note that the use of the game engine is subject to the Unreal(R) Engine End User
- License Agreement at https://www.unrealengine.com/en-US/eula/unreal
-
- License Usage
-
- Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
- this file in accordance with the end user license agreement provided with the
- software or, alternatively, in accordance with the terms contained
- in a written agreement between you and Audiokinetic Inc.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #include "AkAudioModule.h"
- #include "AkAudioDevice.h"
- #include "AkAudioStyle.h"
- #include "AkSettings.h"
- #include "AkSettingsPerUser.h"
- #include "WwiseUnrealDefines.h"
- #include "Wwise/WwiseResourceLoader.h"
- #include "Wwise/WwiseSoundEngineModule.h"
- #include "WwiseInitBankLoader/WwiseInitBankLoader.h"
- #include "Misc/ScopedSlowTask.h"
- #include "UObject/UObjectIterator.h"
- #include "Wwise/API/WwiseSoundEngineAPI.h"
- #if WITH_EDITORONLY_DATA
- #include "Wwise/WwiseFileHandlerModule.h"
- #include "Wwise/WwiseProjectDatabase.h"
- #include "Wwise/WwiseDataStructure.h"
- #include "Wwise/WwiseResourceCooker.h"
- #endif
- #if WITH_EDITOR
- #include "AssetRegistry/AssetRegistryModule.h"
- #include "HAL/FileManager.h"
- #endif
- #include "Async/Async.h"
- IMPLEMENT_MODULE(FAkAudioModule, AkAudio)
- #define LOCTEXT_NAMESPACE "AkAudio"
- FAkAudioModule* FAkAudioModule::AkAudioModuleInstance = nullptr;
- FSimpleMulticastDelegate FAkAudioModule::OnModuleInitialized;
- FSimpleMulticastDelegate FAkAudioModule::OnWwiseAssetDataReloaded;
- // WwiseUnrealHelper overrides
- namespace WwiseUnrealHelper
- {
- static FString GetWwisePluginDirectoryImpl()
- {
- return FAkPlatform::GetWwisePluginDirectory();
- }
- static FString GetWwiseProjectPathImpl()
- {
- FString projectPath;
- if (auto* settings = GetDefault<UAkSettings>())
- {
- projectPath = settings->WwiseProjectPath.FilePath;
- if (FPaths::IsRelative(projectPath))
- {
- projectPath = FPaths::ConvertRelativePathToFull(GetProjectDirectory(), projectPath);
- }
- #if PLATFORM_WINDOWS
- projectPath.ReplaceInline(TEXT("/"), TEXT("\\"));
- #endif
- }
- return projectPath;
- }
- static FString GetSoundBankDirectoryImpl()
- {
- const UAkSettingsPerUser* UserSettings = GetDefault<UAkSettingsPerUser>();
- FString SoundBankDirectory;
- if (UserSettings && !UserSettings->RootOutputPathOverride.Path.IsEmpty())
- {
- SoundBankDirectory = UserSettings->RootOutputPathOverride.Path;
- if(FPaths::IsRelative(UserSettings->RootOutputPathOverride.Path))
- {
- SoundBankDirectory = FPaths::Combine(GetContentDirectory(), UserSettings->RootOutputPathOverride.Path);
- }
- }
- else if (const UAkSettings* AkSettings = GetDefault<UAkSettings>())
- {
- if(AkSettings->RootOutputPath.Path.IsEmpty())
- {
- return {};
- }
- SoundBankDirectory = AkSettings->RootOutputPath.Path;
- if(FPaths::IsRelative(AkSettings->RootOutputPath.Path))
- {
- SoundBankDirectory = FPaths::Combine(GetContentDirectory(), AkSettings->RootOutputPath.Path);
- }
- }
- else
- {
- UE_LOG(LogAkAudio, Warning, TEXT("WwiseUnrealHelper::GetSoundBankDirectory : Please set the Generated Soundbanks Folder in Wwise settings. Otherwise, sound will not function."));
- return {};
- }
- FPaths::CollapseRelativeDirectories(SoundBankDirectory);
- if(!SoundBankDirectory.EndsWith(TEXT("/")))
- {
- SoundBankDirectory.AppendChar('/');
- }
- return SoundBankDirectory;
- }
- static FString GetStagePathImpl()
- {
- const UAkSettings* Settings = GetDefault<UAkSettings>();
- #if WITH_EDITORONLY_DATA
- if (Settings && !Settings->WwiseStagingDirectory.Path.IsEmpty())
- {
- return Settings->WwiseStagingDirectory.Path;
- }
- return TEXT("WwiseAudio");
- #endif
- if (Settings && !Settings->WwiseStagingDirectory.Path.IsEmpty())
- {
- return FPaths::ProjectContentDir() / Settings->WwiseStagingDirectory.Path;
- }
- return FPaths::ProjectContentDir() / TEXT("WwiseAudio");
- }
- }
- void FAkAudioModule::StartupModule()
- {
- IWwiseSoundEngineModule::ForceLoadModule();
- WwiseUnrealHelper::SetHelperFunctions(
- WwiseUnrealHelper::GetWwisePluginDirectoryImpl,
- WwiseUnrealHelper::GetWwiseProjectPathImpl,
- WwiseUnrealHelper::GetSoundBankDirectoryImpl,
- WwiseUnrealHelper::GetStagePathImpl);
- #if WITH_EDITOR
- // It is not wanted to initialize the SoundEngine while running the GenerateSoundBanks commandlet.
- if (IsRunningCommandlet())
- {
- // We COULD use GetRunningCommandletClass(), but unfortunately it is set to nullptr in OnPostEngineInit.
- // We need to parse the command line.
- FString CmdLine(FCommandLine::Get());
- if (CmdLine.Contains(TEXT("run=GenerateSoundBanks")))
- {
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::StartupModule: Detected GenerateSoundBanks commandlet is running. AkAudioModule will not be initialized."));
- return;
- }
- #if WITH_EDITORONLY_DATA
- if(!IWwiseProjectDatabaseModule::ShouldInitializeProjectDatabase())
- {
- // Initialize the Rersource Cooker
- IWwiseResourceCookerModule::GetModule();
- }
- #endif
- }
- #endif
- if (AkAudioModuleInstance == this)
- {
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::StartupModule: AkAudioModuleInstance already exists."));
- return;
- }
- UE_CLOG(AkAudioModuleInstance, LogAkAudio, Warning, TEXT("FAkAudioModule::StartupModule: Updating AkAudioModuleInstance from (%p) to (%p)! Previous Module instance was improperly shut down!"), AkAudioModuleInstance, this);
- AkAudioModuleInstance = this;
- FScopedSlowTask SlowTask(0, LOCTEXT("InitWwisePlugin", "Initializing Wwise Plug-in AkAudioModule..."));
- UpdateWwiseResourceLoaderSettings();
-
- #if WITH_EDITORONLY_DATA
- if (auto* AkSettings = GetDefault<UAkSettings>())
- {
- if (AkSettings->AreSoundBanksGenerated())
- {
- ParseGeneratedSoundBankData();
- FWwiseInitBankLoader::Get()->UpdateInitBankInSettings();
- }
- }
- // Loading the File Handler Module, in case it loads a different module with UStructs, so it gets packaged (Ex.: Simple External Source Manager)
- IWwiseFileHandlerModule::GetModule();
- #endif
- AkAudioDevice = new FAkAudioDevice;
- if (!AkAudioDevice)
- {
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::StartupModule: Couldn't create FAkAudioDevice. AkAudioModule will not be fully initialized."));
- bModuleInitialized = true;
- return;
- }
- if (!AkAudioDevice->Init())
- {
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::StartupModule: Couldn't initialize FAkAudioDevice. AkAudioModule will not be fully initialized."));
- bModuleInitialized = true;
- delete AkAudioDevice;
- AkAudioDevice = nullptr;
- return;
- }
- //Load init bank in Runtime
- UE_LOG(LogAkAudio, VeryVerbose, TEXT("FAkAudioModule::StartupModule: Loading Init Bank."));
- FWwiseInitBankLoader::Get()->LoadInitBank();
- OnTick = FTickerDelegate::CreateRaw(AkAudioDevice, &FAkAudioDevice::Update);
- TickDelegateHandle = FCoreTickerType::GetCoreTicker().AddTicker(OnTick);
- AkAudioDevice->LoadDelayedObjects();
- UE_LOG(LogAkAudio, VeryVerbose, TEXT("FAkAudioModule::StartupModule: Module Initialized."));
- OnModuleInitialized.Broadcast();
- bModuleInitialized = true;
- }
- void FAkAudioModule::ShutdownModule()
- {
- UE_CLOG(AkAudioModuleInstance && AkAudioModuleInstance != this, LogAkAudio, Warning, TEXT("FAkAudioModule::ShutdownModule: Shutting down a different instance (%p) that was initially instantiated (%p)!"), this, AkAudioModuleInstance);
- FCoreTickerType::GetCoreTicker().RemoveTicker(TickDelegateHandle);
- if (AkAudioDevice)
- {
- AkAudioDevice->Teardown();
- delete AkAudioDevice;
- AkAudioDevice = nullptr;
- }
- if (IWwiseSoundEngineModule::IsAvailable())
- {
- WwiseUnrealHelper::SetHelperFunctions(nullptr, nullptr, nullptr, nullptr);
- }
- AkAudioModuleInstance = nullptr;
- }
- FAkAudioDevice* FAkAudioModule::GetAkAudioDevice() const
- {
- return AkAudioDevice;
- }
- void FAkAudioModule::ReloadWwiseAssetData() const
- {
- SCOPED_AKAUDIO_EVENT(TEXT("ReloadWwiseAssetData"));
- if (FAkAudioDevice::IsInitialized())
- {
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::ReloadWwiseAssetData : Reloading Wwise asset data."));
- if (AkAudioDevice)
- {
- AkAudioDevice->ClearSoundBanksAndMedia();
- }
-
- auto* InitBankLoader = FWwiseInitBankLoader::Get();
- if (LIKELY(InitBankLoader))
- {
- InitBankLoader->LoadInitBank();
- }
- else
- {
- UE_LOG(LogAkAudio, Error, TEXT("LoadInitBank: WwiseInitBankLoader is not initialized."));
- }
- for (TObjectIterator<UAkAudioType> AudioAssetIt; AudioAssetIt; ++AudioAssetIt)
- {
- AudioAssetIt->LoadData();
- }
- OnWwiseAssetDataReloaded.Broadcast();
- }
- else
- {
- UE_LOG(LogAkAudio, Verbose, TEXT("FAkAudioModule::ReloadWwiseAssetData : Skipping asset data reload because the SoundEngine is not initialized."));
- }
- }
- void FAkAudioModule::UpdateWwiseResourceLoaderSettings()
- {
- SCOPED_AKAUDIO_EVENT(TEXT("UpdateWwiseResourceLoaderSettings"));
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::UpdateWwiseResourceLoaderSettings : Updating Resource Loader settings."));
- auto* ResourceLoader = FWwiseResourceLoader::Get();
- if (!ResourceLoader)
- {
- UE_LOG(LogAkAudio, Error, TEXT("FAkAudioModule::UpdateWwiseResourceLoaderSettings : No Resource Loader!"));
- return;
- }
- auto* ResourceLoaderImpl = ResourceLoader->ResourceLoaderImpl.Get();
- if (!ResourceLoaderImpl)
- {
- UE_LOG(LogAkAudio, Error, TEXT("FAkAudioModule::UpdateWwiseResourceLoaderSettings : No Resource Loader Impl!"));
- return;
- }
- ResourceLoaderImpl->StagePath = WwiseUnrealHelper::GetStagePathImpl();
- #if WITH_EDITORONLY_DATA
- ResourceLoaderImpl->GeneratedSoundBanksPath = FDirectoryPath{WwiseUnrealHelper::GetSoundBankDirectory()};
- #endif
- }
- #if WITH_EDITORONLY_DATA
- void FAkAudioModule::ParseGeneratedSoundBankData()
- {
- SCOPED_AKAUDIO_EVENT(TEXT("ParseGeneratedSoundBankData"));
- if (auto* AkSettings = GetDefault<UAkSettings>())
- {
- if (!AkSettings->AreSoundBanksGenerated())
- {
- UE_LOG(LogAkAudio, Warning, TEXT("FAkAudioModule::ParseGeneratedSoundBankData: SoundBanks are not yet generated, nothing to parse.\nCurrent Generated SoundBanks path is: %s"), *WwiseUnrealHelper::GetSoundBankDirectory());
- return;
- }
- }
- UE_LOG(LogAkAudio, Log, TEXT("FAkAudioModule::ParseGeneratedSoundBankData : Parsing Wwise project data."));
- auto* ProjectDatabase = FWwiseProjectDatabase::Get();
- if (UNLIKELY(!ProjectDatabase))
- {
- UE_LOG(LogAkAudio, Warning, TEXT("FAkAudioModule::ParseGeneratedSoundBankData : Could not get FWwiseProjectDatabase instance. Generated sound data will not be parsed."));
- }
- else
- {
- ProjectDatabase->UpdateDataStructure();
- }
- }
- #endif
- #undef LOCTEXT_NAMESPACE
|