/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include #include #include #include #include #include #include #include #include #include #if defined(AUDIO_SYSTEM_EDITOR) #include #include struct IEditor; #endif // AUDIO_SYSTEM_EDITOR namespace Audio { // Module globals/statics CSoundCVars g_audioCVars; CAudioLogger g_audioLogger; AZ::EnvironmentVariable g_audioVerbosityVar; namespace Platform { void InitializeAudio(CSoundCVars& audioCVars, CAudioLogger& audioLogger); } } // namespace Audio namespace AudioSystemGem { #if defined(AUDIO_SYSTEM_EDITOR) IEditor* g_editor = nullptr; #endif // AUDIO_SYSTEM_EDITOR void AudioSystemGemSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) { serialize->Class() ->Version(0) ; if (AZ::EditContext* ec = serialize->GetEditContext()) { ec->Class("Audio System Gem", "Audio System handles requests and managages data related to the audio sub-system") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System")) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } } } void AudioSystemGemSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC("AudioSystemGemService")); } void AudioSystemGemSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("AudioSystemGemService")); } void AudioSystemGemSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { AZ_UNUSED(required); } void AudioSystemGemSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) { AZ_UNUSED(dependent); } void AudioSystemGemSystemComponent::Init() { m_loseFocusRequest.nFlags = Audio::eARF_PRIORITY_HIGH; m_loseFocusRequest.pData = &m_loseFocusData; m_getFocusRequest.nFlags = Audio::eARF_PRIORITY_HIGH; m_getFocusRequest.pData = &m_getFocusData; } void AudioSystemGemSystemComponent::Activate() { Audio::Gem::AudioSystemGemRequestBus::Handler::BusConnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); #if defined(AUDIO_SYSTEM_EDITOR) AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); #endif // AUDIO_SYSTEM_EDITOR } void AudioSystemGemSystemComponent::Deactivate() { Audio::Gem::AudioSystemGemRequestBus::Handler::BusDisconnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); #if defined(AUDIO_SYSTEM_EDITOR) AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); #endif // AUDIO_SYSTEM_EDITOR } bool AudioSystemGemSystemComponent::Initialize(const SSystemInitParams* initParams) { using namespace Audio; // When nullptr is passed, create a NullAudioSystem instead of the real thing. if (!initParams) { return CreateNullAudioSystem(); } g_audioCVars.RegisterVariables(); #if defined(INCLUDE_AUDIO_PRODUCTION_CODE) g_audioVerbosityVar = AZ::Environment::CreateVariable("AudioLogVerbosity"); g_audioVerbosityVar.Set(&g_audioCVars.m_nAudioLoggingOptions); #endif // INCLUDE_AUDIO_PRODUCTION_CODE bool success = false; // initialize audio system memory pool if (!AZ::AllocatorInstance::IsReady()) { const size_t poolSize = g_audioCVars.m_nATLPoolSize << 10; AudioSystemAllocator::Descriptor allocDesc; // Generic Allocator: allocDesc.m_allocationRecords = true; allocDesc.m_heap.m_numFixedMemoryBlocks = 1; allocDesc.m_heap.m_fixedMemoryBlocksByteSize[0] = poolSize; allocDesc.m_heap.m_fixedMemoryBlocks[0] = AZ::AllocatorInstance::Get().Allocate( allocDesc.m_heap.m_fixedMemoryBlocksByteSize[0], allocDesc.m_heap.m_memoryBlockAlignment ); AZ::AllocatorInstance::Create(allocDesc); } if (CreateAudioSystem()) { Platform::InitializeAudio(g_audioCVars, g_audioLogger); g_audioLogger.Log(eALT_ALWAYS, "AudioSystem created!"); // Initialize the implementation module... bool initImplSuccess = false; Gem::AudioEngineGemRequestBus::BroadcastResult(initImplSuccess, &Gem::AudioEngineGemRequestBus::Events::Initialize, initParams); if (initImplSuccess) { PrepareAudioSystem(); GetISystem()->GetISystemEventDispatcher()->RegisterListener(this); } else { if (Gem::AudioEngineGemRequestBus::HasHandlers()) { g_audioLogger.Log(eALT_ERROR, "The Audio Engine did not initialize correctly!"); } else { g_audioLogger.Log(eALT_WARNING, "Running without any AudioEngine!"); } } success = true; } return success; } bool AudioSystemGemSystemComponent::CreateNullAudioSystem() { m_audioSystem = AZStd::make_unique(); return (m_audioSystem != nullptr); } void AudioSystemGemSystemComponent::Release() { Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::Release); Audio::Gem::AudioEngineGemRequestBus::Broadcast(&Audio::Gem::AudioEngineGemRequestBus::Events::Release); // Delete the Audio System // It should be the last object that is freed from the audio system memory pool before the allocator is destroyed. m_audioSystem.reset(); if (AZ::AllocatorInstance::IsReady()) { AZ::AllocatorInstance::Destroy(); } Audio::g_audioVerbosityVar.Reset(); Audio::g_audioCVars.UnregisterVariables(); GetISystem()->GetISystemEventDispatcher()->RemoveListener(this); } void AudioSystemGemSystemComponent::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) { switch (event) { case ESYSTEM_EVENT_LEVEL_LOAD_START: { AZ::AllocatorInstance::Get().GarbageCollect(); break; } case ESYSTEM_EVENT_LEVEL_POST_UNLOAD: { AZ::AllocatorInstance::Get().GarbageCollect(); break; } } } void AudioSystemGemSystemComponent::OnApplicationConstrained(Event) { Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, m_loseFocusRequest); } void AudioSystemGemSystemComponent::OnApplicationUnconstrained(Event) { Audio::AudioSystemRequestBus::Broadcast(&Audio::AudioSystemRequestBus::Events::PushRequest, m_getFocusRequest); } #if defined(AUDIO_SYSTEM_EDITOR) void AudioSystemGemSystemComponent::NotifyIEditorAvailable(IEditor* editor) { g_editor = editor; } void AudioSystemGemSystemComponent::NotifyRegisterViews() { if (g_editor) { if (m_editorPlugin) { m_editorPlugin->Release(); } m_editorPlugin.reset(new CAudioControlsEditorPlugin(g_editor)); } } #endif // AUDIO_SYSTEM_EDITOR bool AudioSystemGemSystemComponent::CreateAudioSystem() { AZ_Assert(!Audio::AudioSystemRequestBus::HasHandlers(), "CreateAudioSystem - The AudioSystemRequestBus is already set up and connected!"); bool success = false; m_audioSystem = AZStd::make_unique(); if (m_audioSystem) { Audio::AudioSystemRequestBus::BroadcastResult(success, &Audio::AudioSystemRequestBus::Events::Initialize); } else { Audio::g_audioLogger.Log(Audio::eALT_ERROR, "Could not create AudioSystem!"); } return success; } void AudioSystemGemSystemComponent::PrepareAudioSystem() { using namespace Audio; // This is called when a new audio implementation has been set, // so update the controls path before we start loading data... AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::UpdateControlsPath); // Must be blocking requests. SAudioRequest oAudioRequestData; oAudioRequestData.nFlags = eARF_PRIORITY_HIGH | eARF_EXECUTE_BLOCKING; const char* controlsPath = nullptr; AudioSystemRequestBus::BroadcastResult(controlsPath, &AudioSystemRequestBus::Events::GetControlsPath); SAudioManagerRequestData oAMData(controlsPath, eADS_GLOBAL); oAudioRequestData.pData = &oAMData; AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); SAudioManagerRequestData oAMData2(controlsPath, eADS_GLOBAL); oAudioRequestData.pData = &oAMData2; AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); SAudioManagerRequestData oAMData3(ATLInternalControlIDs::GlobalPreloadRequestID); oAudioRequestData.pData = &oAMData3; AudioSystemRequestBus::Broadcast(&AudioSystemRequestBus::Events::PushRequestBlocking, oAudioRequestData); } } // namespace AudioSystemGem