@@ -132,9 +132,7 @@ int32 AudioClip::GetFirstBufferIndex(float time, float& offset) const
|
||||
if (_buffersStartTimes[i + 1] > time)
|
||||
{
|
||||
offset = time - _buffersStartTimes[i];
|
||||
#if BUILD_DEBUG
|
||||
ASSERT(Math::Abs(GetBufferStartTime(i) + offset - time) < 0.001f);
|
||||
#endif
|
||||
ASSERT_LOW_LAYER(Math::Abs(GetBufferStartTime(i) + offset - time) < 0.001f);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class AudioSource;
|
||||
API_CLASS(NoSpawn) class FLAXENGINE_API AudioClip : public BinaryAsset, public StreamableResource
|
||||
{
|
||||
DECLARE_BINARY_ASSET_HEADER(AudioClip, 2);
|
||||
friend class AudioBackendOAL;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "Engine/Audio/AudioListener.h"
|
||||
#include "Engine/Audio/AudioSource.h"
|
||||
#include "Engine/Audio/AudioSettings.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Level/Level.h"
|
||||
#include "Engine/Video/VideoPlayer.h"
|
||||
|
||||
// Include OpenAL library
|
||||
// Source: https://github.com/kcat/openal-soft
|
||||
@@ -73,6 +76,7 @@ namespace ALC
|
||||
ALCdevice* Device = nullptr;
|
||||
ALCcontext* Context = nullptr;
|
||||
AudioBackend::FeatureFlags Features = AudioBackend::FeatureFlags::None;
|
||||
bool Inited = false;
|
||||
CriticalSection Locker;
|
||||
Dictionary<uint32, SourceData> SourcesData;
|
||||
|
||||
@@ -164,12 +168,9 @@ namespace ALC
|
||||
float Time;
|
||||
};
|
||||
|
||||
void RebuildContext(const Array<AudioSourceState>& states)
|
||||
void RebuildContext()
|
||||
{
|
||||
LOG(Info, "Rebuilding audio contexts");
|
||||
|
||||
ClearContext();
|
||||
|
||||
if (Device == nullptr)
|
||||
return;
|
||||
|
||||
@@ -182,10 +183,16 @@ namespace ALC
|
||||
|
||||
Context = alcCreateContext(Device, attrList);
|
||||
alcMakeContextCurrent(Context);
|
||||
|
||||
}
|
||||
|
||||
void RebuildListeners()
|
||||
{
|
||||
for (AudioListener* listener : Audio::Listeners)
|
||||
Listener::Rebuild(listener);
|
||||
|
||||
}
|
||||
|
||||
void RebuildSources(const Array<AudioSourceState>& states)
|
||||
{
|
||||
for (int32 i = 0; i < states.Count(); i++)
|
||||
{
|
||||
AudioSource* source = Audio::Sources[i];
|
||||
@@ -205,6 +212,13 @@ namespace ALC
|
||||
}
|
||||
}
|
||||
|
||||
void RebuildContext(const Array<AudioSourceState>& states)
|
||||
{
|
||||
RebuildContext();
|
||||
RebuildListeners();
|
||||
RebuildSources(states);
|
||||
}
|
||||
|
||||
void RebuildContext(bool isChangingDevice)
|
||||
{
|
||||
Array<AudioSourceState> states;
|
||||
@@ -629,6 +643,7 @@ AudioBackend::FeatureFlags AudioBackendOAL::Base_Features()
|
||||
|
||||
void AudioBackendOAL::Base_OnActiveDeviceChanged()
|
||||
{
|
||||
PROFILE_CPU();
|
||||
PROFILE_MEM(Audio);
|
||||
|
||||
// Cleanup
|
||||
@@ -659,9 +674,55 @@ void AudioBackendOAL::Base_OnActiveDeviceChanged()
|
||||
LOG(Fatal, "Failed to open OpenAL device ({0}).", String(name));
|
||||
return;
|
||||
}
|
||||
if (ALC::Inited)
|
||||
LOG(Info, "Changed audio device to: {}", String(Audio::GetActiveDevice()->Name));
|
||||
|
||||
// Setup
|
||||
ALC::RebuildContext(states);
|
||||
// Rebuild context
|
||||
ALC::RebuildContext();
|
||||
if (ALC::Inited)
|
||||
{
|
||||
// Reload all audio clips to recreate their buffers
|
||||
for (Asset* asset : Content::GetAssets())
|
||||
{
|
||||
if (auto* audioClip = ScriptingObject::Cast<AudioClip>(asset))
|
||||
{
|
||||
ScopeLock lock(audioClip->Locker);
|
||||
|
||||
// Clear old buffer IDs
|
||||
for (uint32& bufferID : audioClip->Buffers)
|
||||
bufferID = 0;
|
||||
|
||||
if (audioClip->IsStreamable())
|
||||
{
|
||||
// Let the streaming recreate missing buffers
|
||||
audioClip->RequestStreamingUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reload audio clip
|
||||
auto assetLock = audioClip->Storage->Lock();
|
||||
audioClip->LoadChunk(0);
|
||||
audioClip->Buffers[0] = AudioBackend::Buffer::Create();
|
||||
audioClip->WriteBuffer(0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload all videos to recreate their buffers
|
||||
for (VideoPlayer* videoPlayer : Level::GetActors<VideoPlayer>(true))
|
||||
{
|
||||
VideoBackendPlayer& player = videoPlayer->_player;
|
||||
|
||||
// Clear audio state
|
||||
for (uint32& bufferID : player.AudioBuffers)
|
||||
bufferID = 0;
|
||||
player.NextAudioBuffer = 0;
|
||||
player.AudioSource = 0;
|
||||
}
|
||||
}
|
||||
ALC::RebuildListeners();
|
||||
ALC::RebuildSources(states);
|
||||
}
|
||||
|
||||
void AudioBackendOAL::Base_SetDopplerFactor(float value)
|
||||
@@ -782,6 +843,7 @@ bool AudioBackendOAL::Base_Init()
|
||||
if (ALC::IsExtensionSupported("AL_SOFT_source_spatialize"))
|
||||
ALC::Features = EnumAddFlags(ALC::Features, FeatureFlags::SpatialMultiChannel);
|
||||
#endif
|
||||
ALC::Inited = true;
|
||||
|
||||
// Log service info
|
||||
LOG(Info, "{0} ({1})", String(alGetString(AL_RENDERER)), String(alGetString(AL_VERSION)));
|
||||
|
||||
@@ -473,6 +473,19 @@ public:
|
||||
/// <returns>Found actors list.</returns>
|
||||
API_FUNCTION() static Array<Actor*> GetActors(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false);
|
||||
|
||||
/// <summary>
|
||||
/// Finds all the actors of the given type in all the loaded scenes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the object.</typeparam>
|
||||
/// <param name="activeOnly">Finds only active actors.</param>
|
||||
/// <returns>Found actors list.</returns>
|
||||
template<typename T>
|
||||
static Array<T*> GetActors(bool activeOnly = false)
|
||||
{
|
||||
Array<Actor*> actors = GetActors(T::GetStaticClass(), activeOnly);
|
||||
return *(Array<T*>*)&actors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all the scripts of the given type in an actor or all the loaded scenes.
|
||||
/// </summary>
|
||||
|
||||
@@ -15,6 +15,7 @@ class FLAXENGINE_API VideoPlayer : public Actor
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(VideoPlayer);
|
||||
API_AUTO_SERIALIZATION();
|
||||
friend class AudioBackendOAL;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user