diff --git a/Source/Engine/Audio/Audio.cpp b/Source/Engine/Audio/Audio.cpp
index 25b6f39e4..e279f4d44 100644
--- a/Source/Engine/Audio/Audio.cpp
+++ b/Source/Engine/Audio/Audio.cpp
@@ -2,7 +2,6 @@
#include "Audio.h"
#include "AudioBackend.h"
-#include "AudioListener.h"
#include "AudioSettings.h"
#include "FlaxEngine.Gen.h"
#include "Engine/Scripting/ScriptingType.h"
@@ -149,45 +148,6 @@ void Audio::SetEnableHRTF(bool value)
AudioBackend::Listener::ReinitializeAll();
}
-void Audio::OnAddListener(AudioListener* listener)
-{
- ASSERT(!Listeners.Contains(listener));
-
- if (Listeners.Count() >= AUDIO_MAX_LISTENERS)
- {
- LOG(Error, "Unsupported amount of the audio listeners!");
- return;
- }
-
- Listeners.Add(listener);
- AudioBackend::Listener::Reset();
- AudioBackend::Listener::TransformChanged(listener->GetPosition(), listener->GetOrientation());
-}
-
-void Audio::OnRemoveListener(AudioListener* listener)
-{
- if (!Listeners.Remove(listener))
- {
- AudioBackend::Listener::Reset();
- }
-}
-
-void Audio::OnAddSource(AudioSource* source)
-{
- ASSERT(!Sources.Contains(source));
-
- Sources.Add(source);
- AudioBackend::Source::OnAdd(source);
-}
-
-void Audio::OnRemoveSource(AudioSource* source)
-{
- if (!Sources.Remove(source))
- {
- AudioBackend::Source::OnRemove(source);
- }
-}
-
bool AudioService::Init()
{
PROFILE_CPU_NAMED("Audio.Init");
diff --git a/Source/Engine/Audio/Audio.h b/Source/Engine/Audio/Audio.h
index a074fefda..5a82a6da8 100644
--- a/Source/Engine/Audio/Audio.h
+++ b/Source/Engine/Audio/Audio.h
@@ -97,11 +97,4 @@ public:
///
/// The value.
API_PROPERTY() static void SetEnableHRTF(bool value);
-
-public:
- static void OnAddListener(AudioListener* listener);
- static void OnRemoveListener(AudioListener* listener);
-
- static void OnAddSource(AudioSource* source);
- static void OnRemoveSource(AudioSource* source);
};
diff --git a/Source/Engine/Audio/AudioBackend.h b/Source/Engine/Audio/AudioBackend.h
index e7424e1ad..ee94e21a3 100644
--- a/Source/Engine/Audio/AudioBackend.h
+++ b/Source/Engine/Audio/AudioBackend.h
@@ -32,32 +32,30 @@ private:
virtual void Listener_ReinitializeAll() = 0;
// Source
- virtual void Source_OnAdd(AudioSource* source) = 0;
- virtual void Source_OnRemove(AudioSource* source) = 0;
- virtual void Source_VelocityChanged(AudioSource* source) = 0;
- virtual void Source_TransformChanged(AudioSource* source) = 0;
- virtual void Source_VolumeChanged(AudioSource* source) = 0;
- virtual void Source_PitchChanged(AudioSource* source) = 0;
- virtual void Source_PanChanged(AudioSource* source) = 0;
- virtual void Source_IsLoopingChanged(AudioSource* source) = 0;
- virtual void Source_SpatialSetupChanged(AudioSource* source) = 0;
- virtual void Source_ClipLoaded(AudioSource* source) = 0;
- virtual void Source_Cleanup(AudioSource* source) = 0;
- virtual void Source_Play(AudioSource* source) = 0;
- virtual void Source_Pause(AudioSource* source) = 0;
- virtual void Source_Stop(AudioSource* source) = 0;
- virtual void Source_SetCurrentBufferTime(AudioSource* source, float value) = 0;
- virtual float Source_GetCurrentBufferTime(const AudioSource* source) = 0;
- virtual void Source_SetNonStreamingBuffer(AudioSource* source) = 0;
- virtual void Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount) = 0;
- virtual void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) = 0;
- virtual void Source_QueueBuffer(AudioSource* source, uint32 bufferId) = 0;
- virtual void Source_DequeueProcessedBuffers(AudioSource* source) = 0;
+ virtual uint32 Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler) = 0;
+ virtual void Source_Remove(uint32 sourceID) = 0;
+ virtual void Source_VelocityChanged(uint32 sourceID, const Vector3& velocity) = 0;
+ virtual void Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation) = 0;
+ virtual void Source_VolumeChanged(uint32 sourceID, float volume) = 0;
+ virtual void Source_PitchChanged(uint32 sourceID, float pitch) = 0;
+ virtual void Source_PanChanged(uint32 sourceID, float pan) = 0;
+ virtual void Source_IsLoopingChanged(uint32 sourceID, bool loop) = 0;
+ virtual void Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler) = 0;
+ virtual void Source_Play(uint32 sourceID) = 0;
+ virtual void Source_Pause(uint32 sourceID) = 0;
+ virtual void Source_Stop(uint32 sourceID) = 0;
+ virtual void Source_SetCurrentBufferTime(uint32 sourceID, float value) = 0;
+ virtual float Source_GetCurrentBufferTime(uint32 id) = 0;
+ virtual void Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID) = 0;
+ virtual void Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount) = 0;
+ virtual void Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount) = 0;
+ virtual void Source_QueueBuffer(uint32 sourceID, uint32 bufferID) = 0;
+ virtual void Source_DequeueProcessedBuffers(uint32 sourceID) = 0;
// Buffer
virtual uint32 Buffer_Create() = 0;
- virtual void Buffer_Delete(uint32 bufferId) = 0;
- virtual void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) = 0;
+ virtual void Buffer_Delete(uint32 bufferID) = 0;
+ virtual void Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info) = 0;
// Base
virtual const Char* Base_Name() = 0;
@@ -102,109 +100,99 @@ public:
class Source
{
public:
- FORCE_INLINE static void OnAdd(AudioSource* source)
+ FORCE_INLINE static uint32 Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler)
{
- Instance->Source_OnAdd(source);
+ return Instance->Source_Add(format, position, orientation, volume, pitch, pan, loop, spatial, attenuation, minDistance, doppler);
}
- FORCE_INLINE static void OnRemove(AudioSource* source)
+ FORCE_INLINE static void Remove(uint32 sourceID)
{
- Instance->Source_OnRemove(source);
+ Instance->Source_Remove(sourceID);
}
- FORCE_INLINE static void VelocityChanged(AudioSource* source)
+ FORCE_INLINE static void VelocityChanged(uint32 sourceID, const Vector3& velocity)
{
- Instance->Source_VelocityChanged(source);
+ Instance->Source_VelocityChanged(sourceID, velocity);
}
- FORCE_INLINE static void TransformChanged(AudioSource* source)
+ FORCE_INLINE static void TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation)
{
- Instance->Source_TransformChanged(source);
+ Instance->Source_TransformChanged(sourceID, position, orientation);
}
- FORCE_INLINE static void VolumeChanged(AudioSource* source)
+ FORCE_INLINE static void VolumeChanged(uint32 sourceID, float volume)
{
- Instance->Source_VolumeChanged(source);
+ Instance->Source_VolumeChanged(sourceID, volume);
}
- FORCE_INLINE static void PitchChanged(AudioSource* source)
+ FORCE_INLINE static void PitchChanged(uint32 sourceID, float pitch)
{
- Instance->Source_PitchChanged(source);
+ Instance->Source_PitchChanged(sourceID, pitch);
}
- FORCE_INLINE static void PanChanged(AudioSource* source)
+ FORCE_INLINE static void PanChanged(uint32 sourceID, float pan)
{
- Instance->Source_PanChanged(source);
+ Instance->Source_PanChanged(sourceID, pan);
}
- FORCE_INLINE static void IsLoopingChanged(AudioSource* source)
+ FORCE_INLINE static void IsLoopingChanged(uint32 sourceID, bool loop)
{
- Instance->Source_IsLoopingChanged(source);
+ Instance->Source_IsLoopingChanged(sourceID, loop);
}
- FORCE_INLINE static void SpatialSetupChanged(AudioSource* source)
+ FORCE_INLINE static void SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler)
{
- Instance->Source_SpatialSetupChanged(source);
+ Instance->Source_SpatialSetupChanged(sourceID, spatial, attenuation, minDistance, doppler);
}
- FORCE_INLINE static void ClipLoaded(AudioSource* source)
+ FORCE_INLINE static void Play(uint32 sourceID)
{
- Instance->Source_ClipLoaded(source);
+ Instance->Source_Play(sourceID);
}
- FORCE_INLINE static void Cleanup(AudioSource* source)
+ FORCE_INLINE static void Pause(uint32 sourceID)
{
- Instance->Source_Cleanup(source);
+ Instance->Source_Pause(sourceID);
}
- FORCE_INLINE static void Play(AudioSource* source)
+ FORCE_INLINE static void Stop(uint32 sourceID)
{
- Instance->Source_Play(source);
+ Instance->Source_Stop(sourceID);
}
- FORCE_INLINE static void Pause(AudioSource* source)
+ FORCE_INLINE static void SetCurrentBufferTime(uint32 sourceID, float value)
{
- Instance->Source_Pause(source);
+ Instance->Source_SetCurrentBufferTime(sourceID, value);
}
- FORCE_INLINE static void Stop(AudioSource* source)
+ FORCE_INLINE static float GetCurrentBufferTime(uint32 sourceID)
{
- Instance->Source_Stop(source);
+ return Instance->Source_GetCurrentBufferTime(sourceID);
}
- FORCE_INLINE static void SetCurrentBufferTime(AudioSource* source, float value)
+ FORCE_INLINE static void SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID)
{
- Instance->Source_SetCurrentBufferTime(source, value);
+ Instance->Source_SetNonStreamingBuffer(sourceID, bufferID);
}
- FORCE_INLINE static float GetCurrentBufferTime(const AudioSource* source)
+ FORCE_INLINE static void GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount)
{
- return Instance->Source_GetCurrentBufferTime(source);
+ Instance->Source_GetProcessedBuffersCount(sourceID, processedBuffersCount);
}
- FORCE_INLINE static void SetNonStreamingBuffer(AudioSource* source)
+ FORCE_INLINE static void GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount)
{
- Instance->Source_SetNonStreamingBuffer(source);
+ Instance->Source_GetQueuedBuffersCount(sourceID, queuedBuffersCount);
}
- FORCE_INLINE static void GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount)
+ FORCE_INLINE static void QueueBuffer(uint32 sourceID, uint32 bufferID)
{
- Instance->Source_GetProcessedBuffersCount(source, processedBuffersCount);
+ Instance->Source_QueueBuffer(sourceID, bufferID);
}
- FORCE_INLINE static void GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount)
+ FORCE_INLINE static void DequeueProcessedBuffers(uint32 sourceID)
{
- Instance->Source_GetQueuedBuffersCount(source, queuedBuffersCount);
- }
-
- FORCE_INLINE static void QueueBuffer(AudioSource* source, uint32 bufferId)
- {
- Instance->Source_QueueBuffer(source, bufferId);
- }
-
- FORCE_INLINE static void DequeueProcessedBuffers(AudioSource* source)
- {
- Instance->Source_DequeueProcessedBuffers(source);
+ Instance->Source_DequeueProcessedBuffers(sourceID);
}
};
@@ -216,14 +204,14 @@ public:
return Instance->Buffer_Create();
}
- FORCE_INLINE static void Delete(uint32 bufferId)
+ FORCE_INLINE static void Delete(uint32 bufferID)
{
- Instance->Buffer_Delete(bufferId);
+ Instance->Buffer_Delete(bufferID);
}
- FORCE_INLINE static void Write(uint32 bufferId, byte* samples, const AudioDataInfo& info)
+ FORCE_INLINE static void Write(uint32 bufferID, byte* samples, const AudioDataInfo& info)
{
- Instance->Buffer_Write(bufferId, samples, info);
+ Instance->Buffer_Write(bufferID, samples, info);
}
};
diff --git a/Source/Engine/Audio/AudioClip.cpp b/Source/Engine/Audio/AudioClip.cpp
index 0abcc5479..93e85f800 100644
--- a/Source/Engine/Audio/AudioClip.cpp
+++ b/Source/Engine/Audio/AudioClip.cpp
@@ -31,16 +31,16 @@ bool AudioClip::StreamingTask::Run()
for (int32 i = 0; i < queue.Count(); i++)
{
const auto idx = queue[i];
- uint32& bufferId = clip->Buffers[idx];
- if (bufferId == 0)
+ uint32& bufferID = clip->Buffers[idx];
+ if (bufferID == 0)
{
- bufferId = AudioBackend::Buffer::Create();
+ bufferID = AudioBackend::Buffer::Create();
}
else
{
// Release unused data
- AudioBackend::Buffer::Delete(bufferId);
- bufferId = 0;
+ AudioBackend::Buffer::Delete(bufferID);
+ bufferID = 0;
}
}
@@ -383,8 +383,8 @@ Asset::LoadResult AudioClip::load()
void AudioClip::unload(bool isReloading)
{
bool hasAnyBuffer = false;
- for (const uint32 bufferId : Buffers)
- hasAnyBuffer |= bufferId != 0;
+ for (const uint32 bufferID : Buffers)
+ hasAnyBuffer |= bufferID != 0;
// Stop any audio sources that are using this clip right now
// TODO: find better way to collect audio sources using audio clip and impl it for AudioStreamingHandler too
@@ -399,10 +399,10 @@ void AudioClip::unload(bool isReloading)
StreamingQueue.Clear();
if (hasAnyBuffer && AudioBackend::Instance)
{
- for (uint32 bufferId : Buffers)
+ for (uint32 bufferID : Buffers)
{
- if (bufferId != 0)
- AudioBackend::Buffer::Delete(bufferId);
+ if (bufferID != 0)
+ AudioBackend::Buffer::Delete(bufferID);
}
}
Buffers.Clear();
@@ -413,8 +413,8 @@ void AudioClip::unload(bool isReloading)
bool AudioClip::WriteBuffer(int32 chunkIndex)
{
// Ignore if buffer is not created
- const uint32 bufferId = Buffers[chunkIndex];
- if (bufferId == 0)
+ const uint32 bufferID = Buffers[chunkIndex];
+ if (bufferID == 0)
return false;
// Ensure audio backend exists
@@ -475,6 +475,6 @@ bool AudioClip::WriteBuffer(int32 chunkIndex)
}
// Write samples to the audio buffer
- AudioBackend::Buffer::Write(bufferId, data.Get(), info);
+ AudioBackend::Buffer::Write(bufferID, data.Get(), info);
return false;
}
diff --git a/Source/Engine/Audio/AudioListener.cpp b/Source/Engine/Audio/AudioListener.cpp
index ce5243869..48cac4205 100644
--- a/Source/Engine/Audio/AudioListener.cpp
+++ b/Source/Engine/Audio/AudioListener.cpp
@@ -3,6 +3,7 @@
#include "AudioListener.h"
#include "Engine/Engine/Time.h"
#include "Engine/Level/Scene/Scene.h"
+#include "Engine/Core/Log.h"
#include "AudioBackend.h"
#include "Audio.h"
@@ -36,9 +37,18 @@ void AudioListener::OnEnable()
{
_prevPos = GetPosition();
_velocity = Vector3::Zero;
-
- Audio::OnAddListener(this);
- GetScene()->Ticking.Update.AddTick(this);
+ if (Audio::Listeners.Count() >= AUDIO_MAX_LISTENERS)
+ {
+ LOG(Error, "Unsupported amount of the audio listeners!");
+ }
+ else
+ {
+ ASSERT(!Audio::Listeners.Contains(this));
+ Audio::Listeners.Add(this);
+ AudioBackend::Listener::Reset();
+ AudioBackend::Listener::TransformChanged(GetPosition(), GetOrientation());
+ GetScene()->Ticking.Update.AddTick(this);
+ }
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
@@ -52,8 +62,11 @@ void AudioListener::OnDisable()
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
- GetScene()->Ticking.Update.RemoveTick(this);
- Audio::OnRemoveListener(this);
+ if (!Audio::Listeners.Remove(this))
+ {
+ GetScene()->Ticking.Update.RemoveTick(this);
+ AudioBackend::Listener::Reset();
+ }
// Base
Actor::OnDisable();
diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp
index dbe57e150..b9e0ed92d 100644
--- a/Source/Engine/Audio/AudioSource.cpp
+++ b/Source/Engine/Audio/AudioSource.cpp
@@ -33,7 +33,7 @@ void AudioSource::SetVolume(float value)
return;
_volume = value;
if (SourceID)
- AudioBackend::Source::VolumeChanged(this);
+ AudioBackend::Source::VolumeChanged(SourceID, _volume);
}
void AudioSource::SetPitch(float value)
@@ -43,7 +43,7 @@ void AudioSource::SetPitch(float value)
return;
_pitch = value;
if (SourceID)
- AudioBackend::Source::PitchChanged(this);
+ AudioBackend::Source::PitchChanged(SourceID, _pitch);
}
void AudioSource::SetPan(float value)
@@ -53,7 +53,7 @@ void AudioSource::SetPan(float value)
return;
_pan = value;
if (SourceID)
- AudioBackend::Source::PanChanged(this);
+ AudioBackend::Source::PanChanged(SourceID, _pan);
}
void AudioSource::SetIsLooping(bool value)
@@ -64,7 +64,7 @@ void AudioSource::SetIsLooping(bool value)
// When streaming we handle looping manually by the proper buffers submission
if (SourceID && !UseStreaming())
- AudioBackend::Source::IsLoopingChanged(this);
+ AudioBackend::Source::IsLoopingChanged(SourceID, _loop);
}
void AudioSource::SetPlayOnStart(bool value)
@@ -84,7 +84,7 @@ void AudioSource::SetMinDistance(float value)
return;
_minDistance = value;
if (SourceID)
- AudioBackend::Source::SpatialSetupChanged(this);
+ AudioBackend::Source::SpatialSetupChanged(SourceID, Is3D(), _attenuation, _minDistance, _dopplerFactor);
}
void AudioSource::SetAttenuation(float value)
@@ -94,7 +94,7 @@ void AudioSource::SetAttenuation(float value)
return;
_attenuation = value;
if (SourceID)
- AudioBackend::Source::SpatialSetupChanged(this);
+ AudioBackend::Source::SpatialSetupChanged(SourceID, Is3D(), _attenuation, _minDistance, _dopplerFactor);
}
void AudioSource::SetDopplerFactor(float value)
@@ -104,7 +104,7 @@ void AudioSource::SetDopplerFactor(float value)
return;
_dopplerFactor = value;
if (SourceID)
- AudioBackend::Source::SpatialSetupChanged(this);
+ AudioBackend::Source::SpatialSetupChanged(SourceID, Is3D(), _attenuation, _minDistance, _dopplerFactor);
}
void AudioSource::SetAllowSpatialization(bool value)
@@ -113,7 +113,7 @@ void AudioSource::SetAllowSpatialization(bool value)
return;
_allowSpatialization = value;
if (SourceID)
- AudioBackend::Source::SpatialSetupChanged(this);
+ AudioBackend::Source::SpatialSetupChanged(SourceID, Is3D(), _attenuation, _minDistance, _dopplerFactor);
}
void AudioSource::Play()
@@ -121,19 +121,26 @@ void AudioSource::Play()
auto state = _state;
if (state == States::Playing)
return;
- if (Clip == nullptr)
+ if (Clip == nullptr || Clip->WaitForLoaded())
{
LOG(Warning, "Cannot play audio source without a clip ({0})", GetNamePath());
return;
}
+ if (SourceID == 0)
+ {
+ // Create audio source
+ SourceID = AudioBackend::Source::Add(Clip->Info(), GetPosition(), GetOrientation(), GetVolume(), GetPitch(), GetPan(), GetIsLooping() && !UseStreaming(), Is3D(), GetAttenuation(), GetMinDistance(), GetDopplerFactor());
+ if (SourceID == 0)
+ {
+ LOG(Warning, "Cannot create audio source ({0})", GetNamePath());
+ return;
+ }
+ }
+
_state = States::Playing;
_isActuallyPlayingSth = false;
- // Don't block scripting if audio is not loaded or has missing streaming data
- if (!Clip->IsLoaded())
- return;
-
// Audio clips with disabled streaming are controlled by audio source, otherwise streaming manager will play it
if (Clip->IsStreamable())
{
@@ -155,7 +162,7 @@ void AudioSource::Play()
else if (SourceID)
{
// Play it right away
- SetNonStreamingBuffer();
+ AudioBackend::Source::SetNonStreamingBuffer(SourceID, Clip->Buffers[0]);
PlayInternal();
}
else
@@ -171,10 +178,9 @@ void AudioSource::Pause()
return;
_state = States::Paused;
-
if (_isActuallyPlayingSth)
{
- AudioBackend::Source::Pause(this);
+ AudioBackend::Source::Pause(SourceID);
_isActuallyPlayingSth = false;
}
}
@@ -188,7 +194,7 @@ void AudioSource::Stop()
_isActuallyPlayingSth = false;
_streamingFirstChunk = 0;
if (SourceID)
- AudioBackend::Source::Stop(this);
+ AudioBackend::Source::Stop(SourceID);
}
float AudioSource::GetTime() const
@@ -196,13 +202,13 @@ float AudioSource::GetTime() const
if (_state == States::Stopped || SourceID == 0 || !Clip->IsLoaded())
return 0.0f;
- float time = AudioBackend::Source::GetCurrentBufferTime(this);
+ float time = AudioBackend::Source::GetCurrentBufferTime(SourceID);
if (UseStreaming())
{
// Apply time offset to the first streaming buffer binded to the source including the already queued buffers
int32 numProcessedBuffers = 0;
- AudioBackend::Source::GetProcessedBuffersCount(const_cast(this), numProcessedBuffers);
+ AudioBackend::Source::GetProcessedBuffersCount(SourceID, numProcessedBuffers);
time += Clip->GetBufferStartTime(_streamingFirstChunk + numProcessedBuffers);
}
@@ -234,7 +240,7 @@ void AudioSource::SetTime(float time)
time = relativeTime;
}
- AudioBackend::Source::SetCurrentBufferTime(this, time);
+ AudioBackend::Source::SetCurrentBufferTime(SourceID, time);
// Restore state if was stopped
if (isActuallyPlayingSth)
@@ -258,31 +264,29 @@ void AudioSource::RequestStreamingBuffersUpdate()
_needToUpdateStreamingBuffers = true;
}
-void AudioSource::Cleanup()
+void AudioSource::OnClipChanged()
{
- _savedState = GetState();
- _savedTime = GetTime();
Stop();
+ // Destroy current source (will be created on the next play), because clip might use different spatial options or audio data format
if (SourceID)
{
- AudioBackend::Source::Cleanup(this);
+ AudioBackend::Source::Remove(SourceID);
SourceID = 0;
}
}
-void AudioSource::OnClipChanged()
-{
- Stop();
- _clipChanged = true;
-}
-
void AudioSource::OnClipLoaded()
{
- AudioBackend::Source::ClipLoaded(this);
+ if (!SourceID)
+ return;
+
+ // Reset spatial and playback
+ AudioBackend::Source::IsLoopingChanged(SourceID, _loop && !UseStreaming());
+ AudioBackend::Source::SpatialSetupChanged(SourceID, Is3D(), _attenuation, _minDistance, _dopplerFactor);
// Start playing if source was waiting for the clip to load
- if (SourceID && _state == States::Playing && !_isActuallyPlayingSth)
+ if (_state == States::Playing && !_isActuallyPlayingSth)
{
if (Clip->IsStreamable())
{
@@ -292,7 +296,7 @@ void AudioSource::OnClipLoaded()
else
{
// Play it right away
- SetNonStreamingBuffer();
+ AudioBackend::Source::SetNonStreamingBuffer(SourceID, Clip->Buffers[0]);
PlayInternal();
}
}
@@ -300,42 +304,14 @@ void AudioSource::OnClipLoaded()
bool AudioSource::UseStreaming() const
{
- return Clip && Clip->IsLoaded() && Clip->IsStreamable();
-}
-
-void AudioSource::Restore()
-{
- if (Clip)
- {
- if (_savedState != States::Stopped)
- Play();
- if (_savedState == States::Paused)
- Pause();
-
- SetTime(_savedTime);
-
- if (_savedState != States::Stopped && UseStreaming())
- RequestStreamingBuffersUpdate();
- }
-}
-
-void AudioSource::SetNonStreamingBuffer()
-{
- ASSERT(Clip && !Clip->IsStreamable());
-
- AudioBackend::Source::SetNonStreamingBuffer(this);
+ if (Clip == nullptr || Clip->WaitForLoaded())
+ return false;
+ return Clip->IsStreamable();
}
void AudioSource::PlayInternal()
{
- if (_clipChanged && SourceID != 0)
- {
- // If clip was changed between source setup (OnEnable) and actual playback start then ensure to flush any runtime properties with the audio backend
- _clipChanged = false;
- AudioBackend::Source::SpatialSetupChanged(this);
- }
- AudioBackend::Source::Play(this);
-
+ AudioBackend::Source::Play(SourceID);
_isActuallyPlayingSth = true;
}
@@ -413,9 +389,9 @@ void AudioSource::Update()
const auto prevVelocity = _velocity;
_velocity = (pos - _prevPos) / dt;
_prevPos = pos;
- if (_velocity != prevVelocity)
+ if (_velocity != prevVelocity && Is3D())
{
- AudioBackend::Source::VelocityChanged(this);
+ AudioBackend::Source::VelocityChanged(SourceID, _velocity);
}
// Skip other update logic if it's not valid streamable source
@@ -429,17 +405,17 @@ void AudioSource::Update()
{
// Get buffers in a queue count
int32 numQueuedBuffers;
- AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
+ AudioBackend::Source::GetQueuedBuffersCount(SourceID, numQueuedBuffers);
// Queue missing buffers
- uint32 bufferId;
- if (numQueuedBuffers < 1 && (bufferId = clip->Buffers[_streamingFirstChunk]) != 0)
+ uint32 bufferID;
+ if (numQueuedBuffers < 1 && (bufferID = clip->Buffers[_streamingFirstChunk]) != 0)
{
- AudioBackend::Source::QueueBuffer(this, bufferId);
+ AudioBackend::Source::QueueBuffer(SourceID, bufferID);
}
- if (numQueuedBuffers < 2 && _streamingFirstChunk + 1 < clip->Buffers.Count() && (bufferId = clip->Buffers[_streamingFirstChunk + 1]) != 0)
+ if (numQueuedBuffers < 2 && _streamingFirstChunk + 1 < clip->Buffers.Count() && (bufferID = clip->Buffers[_streamingFirstChunk + 1]) != 0)
{
- AudioBackend::Source::QueueBuffer(this, bufferId);
+ AudioBackend::Source::QueueBuffer(SourceID, bufferID);
}
// Clear flag
@@ -457,13 +433,13 @@ void AudioSource::Update()
{
// Get the processed buffers count
int32 numProcessedBuffers = 0;
- AudioBackend::Source::GetProcessedBuffersCount(this, numProcessedBuffers);
+ AudioBackend::Source::GetProcessedBuffersCount(SourceID, numProcessedBuffers);
if (numProcessedBuffers > 0)
{
ASSERT(numProcessedBuffers <= ASSET_FILE_DATA_CHUNKS);
// Unbind processed buffers from the source
- AudioBackend::Source::DequeueProcessedBuffers(this);
+ AudioBackend::Source::DequeueProcessedBuffers(SourceID);
// Move the chunk pointer (AudioStreamingHandler will request new chunks streaming)
_streamingFirstChunk += numProcessedBuffers;
@@ -500,27 +476,53 @@ void AudioSource::OnEnable()
{
_prevPos = GetPosition();
_velocity = Vector3::Zero;
- _clipChanged = false;
- Audio::OnAddSource(this);
+ // Add source
+ ASSERT_LOW_LAYER(!Audio::Sources.Contains(this));
+ Audio::Sources.Add(this);
GetScene()->Ticking.Update.AddTick(this);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
+ // Restore playback state
+ if (Clip)
+ {
+ if (_savedState != States::Stopped)
+ Play();
+ if (_savedState == States::Paused)
+ Pause();
+
+ SetTime(_savedTime);
+
+ if (_savedState != States::Stopped && UseStreaming())
+ RequestStreamingBuffersUpdate();
+ }
+
// Base
Actor::OnEnable();
}
void AudioSource::OnDisable()
{
+ // Cache playback state
+ _savedState = GetState();
+ _savedTime = GetTime();
+
+ // End playback
Stop();
+ // Remove source
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetScene()->Ticking.Update.RemoveTick(this);
- Audio::OnRemoveSource(this);
+ if (SourceID)
+ {
+ AudioBackend::Source::Remove(SourceID);
+ SourceID = 0;
+ }
+ Audio::Sources.Remove(this);
// Base
Actor::OnDisable();
@@ -534,9 +536,9 @@ void AudioSource::OnTransformChanged()
_box = BoundingBox(_transform.Translation);
_sphere = BoundingSphere(_transform.Translation, 0.0f);
- if (IsActiveInHierarchy() && SourceID)
+ if (IsActiveInHierarchy() && SourceID && Is3D())
{
- AudioBackend::Source::TransformChanged(this);
+ AudioBackend::Source::TransformChanged(SourceID, _transform.Translation, _transform.Orientation);
}
}
diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h
index f94e04fb9..682c07563 100644
--- a/Source/Engine/Audio/AudioSource.h
+++ b/Source/Engine/Audio/AudioSource.h
@@ -55,7 +55,6 @@ private:
bool _playOnStart;
float _startTime;
bool _allowSpatialization;
- bool _clipChanged = false;
bool _isActuallyPlayingSth = false;
bool _needToUpdateStreamingBuffers = false;
@@ -270,11 +269,6 @@ public:
///
API_PROPERTY() bool UseStreaming() const;
- ///
- /// Restores the saved time position and resumes/pauses the playback based on the state before. Used to restore audio source state after data rebuild (eg. by audio backend).
- ///
- void Restore();
-
public:
///
/// Determines whether this audio source started playing audio via audio backend. After audio play it may wait for audio clip data to be loaded or streamed.
@@ -289,20 +283,10 @@ public:
///
void RequestStreamingBuffersUpdate();
- ///
- /// Cleanups the cached data. Called by the Audio manager.
- ///
- void Cleanup();
-
private:
void OnClipChanged();
void OnClipLoaded();
- ///
- /// Sets the single buffer from the audio clip that is not using dynamic streaming
- ///
- void SetNonStreamingBuffer();
-
///
/// Plays the audio source. Should have buffer(s) binded before.
///
diff --git a/Source/Engine/Audio/Config.h b/Source/Engine/Audio/Config.h
index e824b8e0f..764468ae5 100644
--- a/Source/Engine/Audio/Config.h
+++ b/Source/Engine/Audio/Config.h
@@ -3,6 +3,7 @@
#pragma once
#include "Engine/Core/Config.h"
+#include "Engine/Content/Config.h"
// The maximum amount of listeners used at once
#define AUDIO_MAX_LISTENERS 1
diff --git a/Source/Engine/Audio/None/AudioBackendNone.cpp b/Source/Engine/Audio/None/AudioBackendNone.cpp
index a28fb91b2..4bf2df88f 100644
--- a/Source/Engine/Audio/None/AudioBackendNone.cpp
+++ b/Source/Engine/Audio/None/AudioBackendNone.cpp
@@ -22,91 +22,82 @@ void AudioBackendNone::Listener_ReinitializeAll()
{
}
-void AudioBackendNone::Source_OnAdd(AudioSource* source)
+uint32 AudioBackendNone::Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler)
{
- source->Restore();
+ return 1;
}
-void AudioBackendNone::Source_OnRemove(AudioSource* source)
-{
- source->Cleanup();
-}
-
-void AudioBackendNone::Source_VelocityChanged(AudioSource* source)
+void AudioBackendNone::Source_Remove(uint32 sourceID)
{
}
-void AudioBackendNone::Source_TransformChanged(AudioSource* source)
+void AudioBackendNone::Source_VelocityChanged(uint32 sourceID, const Vector3& velocity)
{
}
-void AudioBackendNone::Source_VolumeChanged(AudioSource* source)
+void AudioBackendNone::Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation)
{
}
-void AudioBackendNone::Source_PitchChanged(AudioSource* source)
+void AudioBackendNone::Source_VolumeChanged(uint32 sourceID, float volume)
{
}
-void AudioBackendNone::Source_PanChanged(AudioSource* source)
+void AudioBackendNone::Source_PitchChanged(uint32 sourceID, float pitch)
{
}
-void AudioBackendNone::Source_IsLoopingChanged(AudioSource* source)
+void AudioBackendNone::Source_PanChanged(uint32 sourceID, float pan)
{
}
-void AudioBackendNone::Source_SpatialSetupChanged(AudioSource* source)
+void AudioBackendNone::Source_IsLoopingChanged(uint32 sourceID, bool loop)
{
}
-void AudioBackendNone::Source_ClipLoaded(AudioSource* source)
+void AudioBackendNone::Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler)
{
}
-void AudioBackendNone::Source_Cleanup(AudioSource* source)
+void AudioBackendNone::Source_Play(uint32 sourceID)
{
}
-void AudioBackendNone::Source_Play(AudioSource* source)
+void AudioBackendNone::Source_Pause(uint32 sourceID)
{
}
-void AudioBackendNone::Source_Pause(AudioSource* source)
+void AudioBackendNone::Source_Stop(uint32 sourceID)
{
}
-void AudioBackendNone::Source_Stop(AudioSource* source)
+void AudioBackendNone::Source_SetCurrentBufferTime(uint32 sourceID, float value)
{
}
-void AudioBackendNone::Source_SetCurrentBufferTime(AudioSource* source, float value)
-{
-}
-
-float AudioBackendNone::Source_GetCurrentBufferTime(const AudioSource* source)
+float AudioBackendNone::Source_GetCurrentBufferTime(uint32 sourceID)
{
return 0.0f;
}
-void AudioBackendNone::Source_SetNonStreamingBuffer(AudioSource* source)
+void AudioBackendNone::Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID)
{
}
-void AudioBackendNone::Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount)
+void AudioBackendNone::Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount)
{
processedBuffersCount = 0;
}
-void AudioBackendNone::Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount)
+void AudioBackendNone::Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount)
{
}
-void AudioBackendNone::Source_QueueBuffer(AudioSource* source, uint32 bufferId)
+void AudioBackendNone::Source_QueueBuffer(uint32 sourceID, uint32 bufferID)
{
}
-void AudioBackendNone::Source_DequeueProcessedBuffers(AudioSource* source)
+void AudioBackendNone::Source_DequeueProcessedBuffers(uint32 sourceID)
{
}
@@ -115,11 +106,11 @@ uint32 AudioBackendNone::Buffer_Create()
return 1;
}
-void AudioBackendNone::Buffer_Delete(uint32 bufferId)
+void AudioBackendNone::Buffer_Delete(uint32 bufferID)
{
}
-void AudioBackendNone::Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info)
+void AudioBackendNone::Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info)
{
}
diff --git a/Source/Engine/Audio/None/AudioBackendNone.h b/Source/Engine/Audio/None/AudioBackendNone.h
index 5a28331b6..6ceb3149e 100644
--- a/Source/Engine/Audio/None/AudioBackendNone.h
+++ b/Source/Engine/Audio/None/AudioBackendNone.h
@@ -17,30 +17,28 @@ public:
void Listener_VelocityChanged(const Vector3& velocity) override;
void Listener_TransformChanged(const Vector3& position, const Quaternion& orientation) override;
void Listener_ReinitializeAll() override;
- void Source_OnAdd(AudioSource* source) override;
- void Source_OnRemove(AudioSource* source) override;
- void Source_VelocityChanged(AudioSource* source) override;
- void Source_TransformChanged(AudioSource* source) override;
- void Source_VolumeChanged(AudioSource* source) override;
- void Source_PitchChanged(AudioSource* source) override;
- void Source_PanChanged(AudioSource* source) override;
- void Source_IsLoopingChanged(AudioSource* source) override;
- void Source_SpatialSetupChanged(AudioSource* source) override;
- void Source_ClipLoaded(AudioSource* source) override;
- void Source_Cleanup(AudioSource* source) override;
- void Source_Play(AudioSource* source) override;
- void Source_Pause(AudioSource* source) override;
- void Source_Stop(AudioSource* source) override;
- void Source_SetCurrentBufferTime(AudioSource* source, float value) override;
- float Source_GetCurrentBufferTime(const AudioSource* source) override;
- void Source_SetNonStreamingBuffer(AudioSource* source) override;
- void Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount) override;
- void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override;
- void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override;
- void Source_DequeueProcessedBuffers(AudioSource* source) override;
+ uint32 Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Remove(uint32 sourceID) override;
+ void Source_VelocityChanged(uint32 sourceID, const Vector3& velocity) override;
+ void Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation) override;
+ void Source_VolumeChanged(uint32 sourceID, float volume) override;
+ void Source_PitchChanged(uint32 sourceID, float pitch) override;
+ void Source_PanChanged(uint32 sourceID, float pan) override;
+ void Source_IsLoopingChanged(uint32 sourceID, bool loop) override;
+ void Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Play(uint32 sourceID) override;
+ void Source_Pause(uint32 sourceID) override;
+ void Source_Stop(uint32 sourceID) override;
+ void Source_SetCurrentBufferTime(uint32 sourceID, float value) override;
+ float Source_GetCurrentBufferTime(uint32 sourceID) override;
+ void Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount) override;
+ void Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount) override;
+ void Source_QueueBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_DequeueProcessedBuffers(uint32 sourceID) override;
uint32 Buffer_Create() override;
- void Buffer_Delete(uint32 bufferId) override;
- void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override;
+ void Buffer_Delete(uint32 bufferID) override;
+ void Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info) override;
const Char* Base_Name() override;
FeatureFlags Base_Features() override;
void Base_OnActiveDeviceChanged() override;
diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
index 77d8f43c9..d29e3a31b 100644
--- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
+++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp
@@ -5,6 +5,7 @@
#include "AudioBackendOAL.h"
#include "Engine/Platform/StringUtils.h"
#include "Engine/Core/Log.h"
+#include "Engine/Core/Collections/Dictionary.h"
#include "Engine/Tools/AudioTool/AudioTool.h"
#include "Engine/Engine/Units.h"
#include "Engine/Profiler/ProfilerCPU.h"
@@ -42,6 +43,8 @@ namespace ALC
ALCdevice* Device = nullptr;
ALCcontext* Context = nullptr;
AudioBackend::FeatureFlags Features = AudioBackend::FeatureFlags::None;
+ CriticalSection Locker;
+ Dictionary SourceIDtoFormat;
bool IsExtensionSupported(const char* extension)
{
@@ -75,32 +78,28 @@ namespace ALC
namespace Source
{
- void Rebuild(AudioSource* source)
+ void Rebuild(uint32& sourceID, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler)
{
- ASSERT(source->SourceID == 0);
- const bool is3D = source->Is3D();
- const bool loop = source->GetIsLooping() && !source->UseStreaming();
-
- uint32 sourceID = 0;
+ ASSERT_LOW_LAYER(sourceID == 0);
alGenSources(1, &sourceID);
- source->SourceID = sourceID;
+ ASSERT_LOW_LAYER(sourceID != 0);
- alSourcef(sourceID, AL_GAIN, source->GetVolume());
- alSourcef(sourceID, AL_PITCH, source->GetPitch());
+ alSourcef(sourceID, AL_GAIN, volume);
+ alSourcef(sourceID, AL_PITCH, pitch);
alSourcef(sourceID, AL_SEC_OFFSET, 0.0f);
alSourcei(sourceID, AL_LOOPING, loop);
- alSourcei(sourceID, AL_SOURCE_RELATIVE, !is3D);
+ alSourcei(sourceID, AL_SOURCE_RELATIVE, !spatial);
alSourcei(sourceID, AL_BUFFER, 0);
- if (is3D)
+ if (spatial)
{
#ifdef AL_SOFT_source_spatialize
alSourcei(sourceID, AL_SOURCE_SPATIALIZE_SOFT, AL_TRUE);
#endif
- alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation());
- alSourcef(sourceID, AL_DOPPLER_FACTOR, source->GetDopplerFactor());
- alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(source->GetMinDistance()));
- alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(source->GetPosition()));
- alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(source->GetVelocity()));
+ alSourcef(sourceID, AL_ROLLOFF_FACTOR, attenuation);
+ alSourcef(sourceID, AL_DOPPLER_FACTOR, doppler);
+ alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(minDistance));
+ alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position));
+ alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(Vector3::Zero));
}
else
{
@@ -111,26 +110,23 @@ namespace ALC
alSource3f(sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
}
#ifdef AL_EXT_STEREO_ANGLES
- const float panAngle = source->GetPan() * PI_HALF;
+ const float panAngle = pan * PI_HALF;
const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians
alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles);
#endif
-
- // Restore state after Cleanup
- source->Restore();
}
}
- void RebuildContext(bool isChangingDevice)
+ struct AudioSourceState
+ {
+ AudioSource::States State;
+ float Time;
+ };
+
+ void RebuildContext(const Array& states)
{
LOG(Info, "Rebuilding audio contexts");
- if (!isChangingDevice)
- {
- for (AudioSource* source : Audio::Sources)
- source->Cleanup();
- }
-
ClearContext();
if (Device == nullptr)
@@ -150,8 +146,39 @@ namespace ALC
for (AudioListener* listener : Audio::Listeners)
Listener::Rebuild(listener);
- for (AudioSource* source : Audio::Sources)
- Source::Rebuild(source);
+ for (int32 i = 0; i < states.Count(); i++)
+ {
+ AudioSource* source = Audio::Sources[i];
+ Source::Rebuild(source->SourceID, source->GetPosition(), source->GetOrientation(), source->GetVolume(), source->GetPitch(), source->GetPan(), source->GetIsLooping() && !source->UseStreaming(), source->Is3D(), source->GetAttenuation(), source->GetMinDistance(), source->GetDopplerFactor());
+
+ if (states.HasItems())
+ {
+ // Restore playback state
+ auto& state = states[i];
+ if (state.State != AudioSource::States::Stopped)
+ source->Play();
+ if (state.State == AudioSource::States::Paused)
+ source->Pause();
+ if (state.State != AudioSource::States::Stopped)
+ source->SetTime(state.Time);
+ }
+ }
+ }
+
+ void RebuildContext(bool isChangingDevice)
+ {
+ Array states;
+ if (!isChangingDevice)
+ {
+ states.EnsureCapacity(Audio::Sources.Count());
+ for (AudioSource* source : Audio::Sources)
+ {
+ states.Add({ source->GetState(), source->GetTime() });
+ source->Stop();
+ }
+ }
+
+ RebuildContext(states);
}
}
@@ -269,74 +296,76 @@ void AudioBackendOAL::Listener_ReinitializeAll()
ALC::RebuildContext(false);
}
-void AudioBackendOAL::Source_OnAdd(AudioSource* source)
+uint32 AudioBackendOAL::Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler)
{
- ALC::Source::Rebuild(source);
+ uint32 sourceID = 0;
+ ALC::Source::Rebuild(sourceID, position, orientation, volume, pitch, pan, loop, spatial, attenuation, minDistance, doppler);
+
+ // Cache audio data format assigned on source (used in Source_GetCurrentBufferTime)
+ ALC::Locker.Lock();
+ ALC::SourceIDtoFormat[sourceID] = format;
+ ALC::Locker.Unlock();
+
+ return sourceID;
}
-void AudioBackendOAL::Source_OnRemove(AudioSource* source)
+void AudioBackendOAL::Source_Remove(uint32 sourceID)
{
- source->Cleanup();
+ alSourcei(sourceID, AL_BUFFER, 0);
+ ALC_CHECK_ERROR(alSourcei);
+ alDeleteSources(1, &sourceID);
+ ALC_CHECK_ERROR(alDeleteSources);
+
+ ALC::Locker.Lock();
+ ALC::SourceIDtoFormat.Remove(sourceID);
+ ALC::Locker.Unlock();
}
-void AudioBackendOAL::Source_VelocityChanged(AudioSource* source)
+void AudioBackendOAL::Source_VelocityChanged(uint32 sourceID, const Vector3& velocity)
{
- if (!source->Is3D())
- return;
- const uint32 sourceID = source->SourceID;
- alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(source->GetVelocity()));
+ alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(velocity));
}
-void AudioBackendOAL::Source_TransformChanged(AudioSource* source)
+void AudioBackendOAL::Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation)
{
- if (!source->Is3D())
- return;
- const uint32 sourceID = source->SourceID;
- alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(source->GetPosition()));
+ alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position));
}
-void AudioBackendOAL::Source_VolumeChanged(AudioSource* source)
+void AudioBackendOAL::Source_VolumeChanged(uint32 sourceID, float volume)
{
- const uint32 sourceID = source->SourceID;
- alSourcef(sourceID, AL_GAIN, source->GetVolume());
+ alSourcef(sourceID, AL_GAIN, volume);
}
-void AudioBackendOAL::Source_PitchChanged(AudioSource* source)
+void AudioBackendOAL::Source_PitchChanged(uint32 sourceID, float pitch)
{
- const uint32 sourceID = source->SourceID;
- alSourcef(sourceID, AL_PITCH, source->GetPitch());
+ alSourcef(sourceID, AL_PITCH, pitch);
}
-void AudioBackendOAL::Source_PanChanged(AudioSource* source)
+void AudioBackendOAL::Source_PanChanged(uint32 sourceID, float pan)
{
#ifdef AL_EXT_STEREO_ANGLES
- const float panAngle = source->GetPan() * PI_HALF;
+ const float panAngle = pan * PI_HALF;
const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians
- const uint32 sourceID = source->SourceID;
alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles);
#endif
}
-void AudioBackendOAL::Source_IsLoopingChanged(AudioSource* source)
+void AudioBackendOAL::Source_IsLoopingChanged(uint32 sourceID, bool loop)
{
- const bool loop = source->GetIsLooping() && !source->UseStreaming();
- const uint32 sourceID = source->SourceID;
alSourcei(sourceID, AL_LOOPING, loop);
}
-void AudioBackendOAL::Source_SpatialSetupChanged(AudioSource* source)
+void AudioBackendOAL::Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler)
{
- const bool is3D = source->Is3D();
- const uint32 sourceID = source->SourceID;
- alSourcei(sourceID, AL_SOURCE_RELATIVE, !is3D);
- if (is3D)
+ alSourcei(sourceID, AL_SOURCE_RELATIVE, !spatial);
+ if (spatial)
{
#ifdef AL_SOFT_source_spatialize
alSourcei(sourceID, AL_SOURCE_SPATIALIZE_SOFT, AL_TRUE);
#endif
- alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation());
- alSourcef(sourceID, AL_DOPPLER_FACTOR, source->GetDopplerFactor());
- alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(source->GetMinDistance()));
+ alSourcef(sourceID, AL_ROLLOFF_FACTOR, attenuation);
+ alSourcef(sourceID, AL_DOPPLER_FACTOR, doppler);
+ alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(minDistance));
}
else
{
@@ -346,46 +375,20 @@ void AudioBackendOAL::Source_SpatialSetupChanged(AudioSource* source)
}
}
-void AudioBackendOAL::Source_ClipLoaded(AudioSource* source)
+void AudioBackendOAL::Source_Play(uint32 sourceID)
{
- if (source->SourceID == 0)
- return;
- const auto clip = source->Clip.Get();
- const bool is3D = source->Is3D();
- const bool loop = source->GetIsLooping() && !clip->IsStreamable();
-
- const uint32 sourceID = source->SourceID;
- alSourcei(sourceID, AL_SOURCE_RELATIVE, !is3D);
- alSourcei(sourceID, AL_LOOPING, loop);
-}
-
-void AudioBackendOAL::Source_Cleanup(AudioSource* source)
-{
- const uint32 sourceID = source->SourceID;
- alSourcei(sourceID, AL_BUFFER, 0);
- ALC_CHECK_ERROR(alSourcei);
- alDeleteSources(1, &sourceID);
- ALC_CHECK_ERROR(alDeleteSources);
-}
-
-void AudioBackendOAL::Source_Play(AudioSource* source)
-{
- const uint32 sourceID = source->SourceID;
alSourcePlay(sourceID);
ALC_CHECK_ERROR(alSourcePlay);
}
-void AudioBackendOAL::Source_Pause(AudioSource* source)
+void AudioBackendOAL::Source_Pause(uint32 sourceID)
{
- const uint32 sourceID = source->SourceID;
alSourcePause(sourceID);
ALC_CHECK_ERROR(alSourcePause);
}
-void AudioBackendOAL::Source_Stop(AudioSource* source)
+void AudioBackendOAL::Source_Stop(uint32 sourceID)
{
- const uint32 sourceID = source->SourceID;
-
// Stop and rewind
alSourceRewind(sourceID);
ALC_CHECK_ERROR(alSourceRewind);
@@ -396,67 +399,61 @@ void AudioBackendOAL::Source_Stop(AudioSource* source)
ALC_CHECK_ERROR(alSourcei);
}
-void AudioBackendOAL::Source_SetCurrentBufferTime(AudioSource* source, float value)
+void AudioBackendOAL::Source_SetCurrentBufferTime(uint32 sourceID, float value)
{
- const uint32 sourceID = source->SourceID;
alSourcef(sourceID, AL_SEC_OFFSET, value);
}
-float AudioBackendOAL::Source_GetCurrentBufferTime(const AudioSource* source)
+float AudioBackendOAL::Source_GetCurrentBufferTime(uint32 sourceID)
{
#if 0
float time;
- alGetSourcef(source->SourceID, AL_SEC_OFFSET, &time);
+ alGetSourcef(sourceID, AL_SEC_OFFSET, &time);
#else
- ASSERT(source->Clip && source->Clip->IsLoaded());
- const AudioDataInfo& clipInfo = source->Clip->AudioHeader.Info;
+ ALC::Locker.Lock();
+ AudioDataInfo clipInfo = ALC::SourceIDtoFormat[sourceID];
+ ALC::Locker.Unlock();
ALint samplesPlayed;
- alGetSourcei(source->SourceID, AL_SAMPLE_OFFSET, &samplesPlayed);
+ alGetSourcei(sourceID, AL_SAMPLE_OFFSET, &samplesPlayed);
const uint32 totalSamples = clipInfo.NumSamples / clipInfo.NumChannels;
- const float time = (samplesPlayed % totalSamples) / static_cast(Math::Max(1U, clipInfo.SampleRate));
+ if (totalSamples > 0)
+ samplesPlayed %= totalSamples;
+ const float time = samplesPlayed / static_cast(Math::Max(1U, clipInfo.SampleRate));
#endif
-
return time;
}
-void AudioBackendOAL::Source_SetNonStreamingBuffer(AudioSource* source)
+void AudioBackendOAL::Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID)
{
- const uint32 bufferId = source->Clip->Buffers[0];
- const uint32 sourceID = source->SourceID;
- alSourcei(sourceID, AL_BUFFER, bufferId);
+ alSourcei(sourceID, AL_BUFFER, bufferID);
ALC_CHECK_ERROR(alSourcei);
}
-void AudioBackendOAL::Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount)
+void AudioBackendOAL::Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount)
{
// Check the first context only
- const uint32 sourceID = source->SourceID;
alGetSourcei(sourceID, AL_BUFFERS_PROCESSED, &processedBuffersCount);
ALC_CHECK_ERROR(alGetSourcei);
}
-void AudioBackendOAL::Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount)
+void AudioBackendOAL::Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount)
{
// Check the first context only
- const uint32 sourceID = source->SourceID;
alGetSourcei(sourceID, AL_BUFFERS_QUEUED, &queuedBuffersCount);
ALC_CHECK_ERROR(alGetSourcei);
}
-void AudioBackendOAL::Source_QueueBuffer(AudioSource* source, uint32 bufferId)
+void AudioBackendOAL::Source_QueueBuffer(uint32 sourceID, uint32 bufferID)
{
- const uint32 sourceID = source->SourceID;
-
// Queue new buffer
- alSourceQueueBuffers(sourceID, 1, &bufferId);
+ alSourceQueueBuffers(sourceID, 1, &bufferID);
ALC_CHECK_ERROR(alSourceQueueBuffers);
}
-void AudioBackendOAL::Source_DequeueProcessedBuffers(AudioSource* source)
+void AudioBackendOAL::Source_DequeueProcessedBuffers(uint32 sourceID)
{
- ALuint buffers[AUDIO_MAX_SOURCE_BUFFERS];
- const uint32 sourceID = source->SourceID;
int32 numProcessedBuffers;
+ ALuint buffers[AUDIO_MAX_SOURCE_BUFFERS];
alGetSourcei(sourceID, AL_BUFFERS_PROCESSED, &numProcessedBuffers);
alSourceUnqueueBuffers(sourceID, numProcessedBuffers, buffers);
ALC_CHECK_ERROR(alSourceUnqueueBuffers);
@@ -464,19 +461,19 @@ void AudioBackendOAL::Source_DequeueProcessedBuffers(AudioSource* source)
uint32 AudioBackendOAL::Buffer_Create()
{
- uint32 bufferId;
- alGenBuffers(1, &bufferId);
+ uint32 bufferID;
+ alGenBuffers(1, &bufferID);
ALC_CHECK_ERROR(alGenBuffers);
- return bufferId;
+ return bufferID;
}
-void AudioBackendOAL::Buffer_Delete(uint32 bufferId)
+void AudioBackendOAL::Buffer_Delete(uint32 bufferID)
{
- alDeleteBuffers(1, &bufferId);
+ alDeleteBuffers(1, &bufferID);
ALC_CHECK_ERROR(alDeleteBuffers);
}
-void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info)
+void AudioBackendOAL::Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info)
{
PROFILE_CPU();
@@ -495,7 +492,7 @@ void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDa
AudioTool::ConvertToFloat(samples, info.BitDepth, sampleBufferFloat, info.NumSamples);
format = GetOpenALBufferFormat(info.NumChannels, 32);
- alBufferData(bufferId, format, sampleBufferFloat, bufferSize, info.SampleRate);
+ alBufferData(bufferID, format, sampleBufferFloat, bufferSize, info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
Allocator::Free(sampleBufferFloat);
}
@@ -507,7 +504,7 @@ void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDa
AudioTool::ConvertBitDepth(samples, info.BitDepth, sampleBuffer16, 16, info.NumSamples);
format = GetOpenALBufferFormat(info.NumChannels, 16);
- alBufferData(bufferId, format, sampleBuffer16, bufferSize, info.SampleRate);
+ alBufferData(bufferID, format, sampleBuffer16, bufferSize, info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
Allocator::Free(sampleBuffer16);
}
@@ -520,13 +517,13 @@ void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDa
for (uint32 i = 0; i < info.NumSamples; i++)
sampleBuffer[i] = ((int8*)samples)[i] + 128;
- alBufferData(bufferId, format, sampleBuffer, bufferSize, info.SampleRate);
+ alBufferData(bufferID, format, sampleBuffer, bufferSize, info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
Allocator::Free(sampleBuffer);
}
else if (format)
{
- alBufferData(bufferId, format, samples, info.NumSamples * (info.BitDepth / 8), info.SampleRate);
+ alBufferData(bufferID, format, samples, info.NumSamples * (info.BitDepth / 8), info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
}
}
@@ -543,7 +540,7 @@ void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDa
AudioTool::ConvertBitDepth(samples, info.BitDepth, sampleBuffer32, 32, info.NumSamples);
format = GetOpenALBufferFormat(info.NumChannels, 32);
- alBufferData(bufferId, format, sampleBuffer32, bufferSize, info.SampleRate);
+ alBufferData(bufferID, format, sampleBuffer32, bufferSize, info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
Allocator::Free(sampleBuffer32);
@@ -558,14 +555,14 @@ void AudioBackendOAL::Buffer_Write(uint32 bufferId, byte* samples, const AudioDa
sampleBuffer[i] = ((int8*)samples)[i] + 128;
format = GetOpenALBufferFormat(info.NumChannels, 16);
- alBufferData(bufferId, format, sampleBuffer, bufferSize, info.SampleRate);
+ alBufferData(bufferID, format, sampleBuffer, bufferSize, info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
Allocator::Free(sampleBuffer);
}
else if (format)
{
- alBufferData(bufferId, format, samples, info.NumSamples * (info.BitDepth / 8), info.SampleRate);
+ alBufferData(bufferID, format, samples, info.NumSamples * (info.BitDepth / 8), info.SampleRate);
ALC_CHECK_ERROR(alBufferData);
}
}
@@ -589,8 +586,18 @@ AudioBackend::FeatureFlags AudioBackendOAL::Base_Features()
void AudioBackendOAL::Base_OnActiveDeviceChanged()
{
// Cleanup
+ Array states;
+ states.EnsureCapacity(Audio::Sources.Count());
for (AudioSource* source : Audio::Sources)
- source->Cleanup();
+ {
+ states.Add({ source->GetState(), source->GetTime() });
+ source->Stop();
+ if (source->SourceID)
+ {
+ Source_Remove(source->SourceID);
+ source->SourceID = 0;
+ }
+ }
ALC::ClearContext();
if (ALC::Device != nullptr)
{
@@ -608,7 +615,7 @@ void AudioBackendOAL::Base_OnActiveDeviceChanged()
}
// Setup
- ALC::RebuildContext(true);
+ ALC::RebuildContext(states);
}
void AudioBackendOAL::Base_SetDopplerFactor(float value)
diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.h b/Source/Engine/Audio/OpenAL/AudioBackendOAL.h
index 3375251a4..258f5e967 100644
--- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.h
+++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.h
@@ -17,30 +17,28 @@ public:
void Listener_VelocityChanged(const Vector3& velocity) override;
void Listener_TransformChanged(const Vector3& position, const Quaternion& orientation) override;
void Listener_ReinitializeAll() override;
- void Source_OnAdd(AudioSource* source) override;
- void Source_OnRemove(AudioSource* source) override;
- void Source_VelocityChanged(AudioSource* source) override;
- void Source_TransformChanged(AudioSource* source) override;
- void Source_VolumeChanged(AudioSource* source) override;
- void Source_PitchChanged(AudioSource* source) override;
- void Source_PanChanged(AudioSource* source) override;
- void Source_IsLoopingChanged(AudioSource* source) override;
- void Source_SpatialSetupChanged(AudioSource* source) override;
- void Source_ClipLoaded(AudioSource* source) override;
- void Source_Cleanup(AudioSource* source) override;
- void Source_Play(AudioSource* source) override;
- void Source_Pause(AudioSource* source) override;
- void Source_Stop(AudioSource* source) override;
- void Source_SetCurrentBufferTime(AudioSource* source, float value) override;
- float Source_GetCurrentBufferTime(const AudioSource* source) override;
- void Source_SetNonStreamingBuffer(AudioSource* source) override;
- void Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount) override;
- void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override;
- void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override;
- void Source_DequeueProcessedBuffers(AudioSource* source) override;
+ uint32 Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Remove(uint32 sourceID) override;
+ void Source_VelocityChanged(uint32 sourceID, const Vector3& velocity) override;
+ void Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation) override;
+ void Source_VolumeChanged(uint32 sourceID, float volume) override;
+ void Source_PitchChanged(uint32 sourceID, float pitch) override;
+ void Source_PanChanged(uint32 sourceID, float pan) override;
+ void Source_IsLoopingChanged(uint32 sourceID, bool loop) override;
+ void Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Play(uint32 sourceID) override;
+ void Source_Pause(uint32 sourceID) override;
+ void Source_Stop(uint32 sourceID) override;
+ void Source_SetCurrentBufferTime(uint32 sourceID, float value) override;
+ float Source_GetCurrentBufferTime(uint32 sourceID) override;
+ void Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount) override;
+ void Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount) override;
+ void Source_QueueBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_DequeueProcessedBuffers(uint32 sourceID) override;
uint32 Buffer_Create() override;
- void Buffer_Delete(uint32 bufferId) override;
- void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override;
+ void Buffer_Delete(uint32 bufferID) override;
+ void Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info) override;
const Char* Base_Name() override;
FeatureFlags Base_Features() override;
void Base_OnActiveDeviceChanged() override;
diff --git a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp
index 4f24013e1..4c6f93947 100644
--- a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp
+++ b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.cpp
@@ -8,7 +8,6 @@
#include "Engine/Core/Collections/ChunkedArray.h"
#include "Engine/Core/Log.h"
#include "Engine/Audio/Audio.h"
-#include "Engine/Audio/AudioSource.h"
#include "Engine/Threading/Threading.h"
#if PLATFORM_WINDOWS
@@ -76,7 +75,7 @@ namespace XAudio2
}
public:
- AudioSource* Source;
+ uint32 SourceID;
void PeekSamples();
};
@@ -85,6 +84,7 @@ namespace XAudio2
{
IXAudio2SourceVoice* Voice;
WAVEFORMATEX Format;
+ AudioDataInfo Info;
XAUDIO2_SEND_DESCRIPTOR Destination;
float StartTimeForQueueBuffer;
float LastBufferStartTime;
@@ -93,6 +93,8 @@ namespace XAudio2
int32 Channels;
bool IsDirty;
bool IsPlaying;
+ bool IsLoop;
+ uint32 LastBufferID;
VoiceCallback Callback;
Source()
@@ -112,6 +114,8 @@ namespace XAudio2
IsDirty = false;
Is3D = false;
IsPlaying = false;
+ IsLoop = false;
+ LastBufferID = 0;
LastBufferStartSamplesPlayed = 0;
BuffersProcessed = 0;
}
@@ -120,17 +124,6 @@ namespace XAudio2
{
return Voice == nullptr;
}
-
- void UpdateTransform(const AudioSource* source)
- {
- Position = source->GetPosition();
- Orientation = source->GetOrientation();
- }
-
- void UpdateVelocity(const AudioSource* source)
- {
- Velocity = source->GetVelocity();
- }
};
struct Buffer
@@ -166,11 +159,11 @@ namespace XAudio2
ChunkedArray Buffers; // TODO: use ChunkedArray for better performance or use buffers pool?
EngineCallback Callback;
- Source* GetSource(const AudioSource* source)
+ Source* GetSource(uint32 sourceID)
{
- if (source->SourceID == 0)
+ if (sourceID == 0)
return nullptr;
- return &Sources[source->SourceID - 1]; // 0 is invalid ID so shift them
+ return &Sources[sourceID - 1]; // 0 is invalid ID so shift them
}
void MarkAllDirty()
@@ -178,9 +171,9 @@ namespace XAudio2
ForceDirty = true;
}
- void QueueBuffer(Source* aSource, const AudioSource* source, const int32 bufferId, XAUDIO2_BUFFER& buffer)
+ void QueueBuffer(Source* aSource, const int32 bufferID, XAUDIO2_BUFFER& buffer)
{
- Buffer* aBuffer = Buffers[bufferId - 1];
+ Buffer* aBuffer = Buffers[bufferID - 1];
buffer.pAudioData = aBuffer->Data.Get();
buffer.AudioBytes = aBuffer->Data.Count();
@@ -200,14 +193,14 @@ namespace XAudio2
void VoiceCallback::OnBufferEnd(void* pBufferContext)
{
- auto aSource = GetSource(Source);
+ auto aSource = GetSource(SourceID);
if (aSource->IsPlaying)
aSource->BuffersProcessed++;
}
void VoiceCallback::PeekSamples()
{
- auto aSource = GetSource(Source);
+ auto aSource = GetSource(SourceID);
XAUDIO2_VOICE_STATE state;
aSource->Voice->GetState(&state);
aSource->LastBufferStartSamplesPlayed = state.SamplesPlayed;
@@ -216,7 +209,7 @@ namespace XAudio2
void AudioBackendXAudio2::Listener_Reset()
{
- XAudio2::Listener->Reset();
+ XAudio2::Listener.Reset();
XAudio2::MarkAllDirty();
}
@@ -238,17 +231,13 @@ void AudioBackendXAudio2::Listener_ReinitializeAll()
// TODO: Implement XAudio2 reinitialization; read HRTF audio value from Audio class
}
-void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
+uint32 AudioBackendXAudio2::Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler)
{
- // Skip if has no clip (needs audio data to create a source - needs data format information)
- if (source->Clip == nullptr || !source->Clip->IsLoaded())
- return;
- auto clip = source->Clip.Get();
ScopeLock lock(XAudio2::Locker);
// Get first free source
XAudio2::Source* aSource = nullptr;
- uint32 sourceID;
+ uint32 sourceID = 0;
for (int32 i = 0; i < XAudio2::Sources.Count(); i++)
{
if (XAudio2::Sources[i].IsFree())
@@ -266,115 +255,124 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
XAudio2::Sources.Add(src);
aSource = &XAudio2::Sources[sourceID];
}
+ sourceID++; // 0 is invalid ID so shift them
// Initialize audio data format information (from clip)
- const auto& header = clip->AudioHeader;
- auto& format = aSource->Format;
- format.wFormatTag = WAVE_FORMAT_PCM;
- format.nChannels = clip->Is3D() ? 1 : header.Info.NumChannels; // 3d audio is always mono (AudioClip auto-converts before buffer write if FeatureFlags::SpatialMultiChannel is unset)
- format.nSamplesPerSec = header.Info.SampleRate;
- format.wBitsPerSample = header.Info.BitDepth;
- format.nBlockAlign = (WORD)(format.nChannels * (format.wBitsPerSample / 8));
- format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
- format.cbSize = 0;
+ aSource->Info = format;
+ auto& aFormat = aSource->Format;
+ aFormat.wFormatTag = WAVE_FORMAT_PCM;
+ aFormat.nChannels = spatial ? 1 : format.NumChannels; // 3d audio is always mono (AudioClip auto-converts before buffer write if FeatureFlags::SpatialMultiChannel is unset)
+ aFormat.nSamplesPerSec = format.SampleRate;
+ aFormat.wBitsPerSample = format.BitDepth;
+ aFormat.nBlockAlign = (WORD)(aFormat.nChannels * (aFormat.wBitsPerSample / 8));
+ aFormat.nAvgBytesPerSec = aFormat.nSamplesPerSec * aFormat.nBlockAlign;
+ aFormat.cbSize = 0;
// Setup dry effect
aSource->Destination.pOutputVoice = XAudio2::MasteringVoice;
// Create voice
- const XAUDIO2_VOICE_SENDS sendList =
- {
- 1,
- &aSource->Destination
- };
+ const XAUDIO2_VOICE_SENDS sendList = { 1, &aSource->Destination };
HRESULT hr = XAudio2::Instance->CreateSourceVoice(&aSource->Voice, &aSource->Format, 0, 2.0f, &aSource->Callback, &sendList);
XAUDIO2_CHECK_ERROR(CreateSourceVoice);
if (FAILED(hr))
- return;
-
- source->SourceID = sourceID + 1; // 0 is invalid ID so shift them
+ return 0;
// Prepare source state
- aSource->Callback.Source = source;
+ aSource->Callback.SourceID = sourceID;
aSource->IsDirty = true;
- aSource->Is3D = source->Is3D();
- aSource->Pitch = source->GetPitch();
- aSource->Pan = source->GetPan();
- aSource->DopplerFactor = source->GetDopplerFactor();
- aSource->Volume = source->GetVolume();
- aSource->MinDistance = source->GetMinDistance();
- aSource->Attenuation = source->GetAttenuation();
- aSource->Channels = format.nChannels;
- aSource->UpdateTransform(source);
- aSource->UpdateVelocity(source);
- hr = aSource->Voice->SetVolume(source->GetVolume());
+ aSource->IsLoop = loop;
+ aSource->Is3D = spatial;
+ aSource->Pitch = pitch;
+ aSource->Pan = pan;
+ aSource->DopplerFactor = doppler;
+ aSource->Volume = volume;
+ aSource->MinDistance = minDistance;
+ aSource->Attenuation = attenuation;
+ aSource->Channels = aFormat.nChannels;
+ aSource->Position = position;
+ aSource->Orientation = orientation;
+ aSource->Velocity = Vector3::Zero;
+ hr = aSource->Voice->SetVolume(volume);
XAUDIO2_CHECK_ERROR(SetVolume);
- source->Restore();
+ return sourceID;
}
-void AudioBackendXAudio2::Source_OnRemove(AudioSource* source)
+void AudioBackendXAudio2::Source_Remove(uint32 sourceID)
{
ScopeLock lock(XAudio2::Locker);
- source->Cleanup();
+ auto aSource = XAudio2::GetSource(sourceID);
+ if (!aSource)
+ return;
+
+ // Free source
+ if (aSource->Voice)
+ {
+ aSource->Voice->DestroyVoice();
+ }
+ aSource->Init();
}
-void AudioBackendXAudio2::Source_VelocityChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_VelocityChanged(uint32 sourceID, const Vector3& velocity)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- aSource->UpdateVelocity(source);
+ aSource->Velocity = velocity;
aSource->IsDirty = true;
}
}
-void AudioBackendXAudio2::Source_TransformChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- aSource->UpdateTransform(source);
+ aSource->Position = position;
+ aSource->Orientation = orientation;
aSource->IsDirty = true;
}
}
-void AudioBackendXAudio2::Source_VolumeChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_VolumeChanged(uint32 sourceID, float volume)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice)
{
- aSource->Volume = source->GetVolume();
- const HRESULT hr = aSource->Voice->SetVolume(source->GetVolume());
+ aSource->Volume = volume;
+ const HRESULT hr = aSource->Voice->SetVolume(volume);
XAUDIO2_CHECK_ERROR(SetVolume);
}
}
-void AudioBackendXAudio2::Source_PitchChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_PitchChanged(uint32 sourceID, float pitch)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- aSource->Pitch = source->GetPitch();
+ aSource->Pitch = pitch;
aSource->IsDirty = true;
}
}
-void AudioBackendXAudio2::Source_PanChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_PanChanged(uint32 sourceID, float pan)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- aSource->Pan = source->GetPan();
+ aSource->Pan = pan;
aSource->IsDirty = true;
}
}
-void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_IsLoopingChanged(uint32 sourceID, bool loop)
{
- auto aSource = XAudio2::GetSource(source);
+ ScopeLock lock(XAudio2::Locker);
+ auto aSource = XAudio2::GetSource(sourceID);
if (!aSource || !aSource->Voice)
return;
+ aSource->IsLoop = loop;
// Skip if has no buffers (waiting for data or sth)
XAUDIO2_VOICE_STATE state;
@@ -382,15 +380,12 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
if (state.BuffersQueued == 0)
return;
- // Looping is defined during buffer submission so reset source buffer (this is called only for non-streamable sources that ue single buffer)
-
- XAudio2::Locker.Lock();
- const uint32 bufferId = source->Clip->Buffers[0];
- XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
- XAudio2::Locker.Unlock();
+ // Looping is defined during buffer submission so reset source buffer (this is called only for non-streamable sources that use a single buffer)
+ const uint32 bufferID = aSource->LastBufferID;
+ XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferID - 1];
HRESULT hr;
- const bool isPlaying = source->IsActuallyPlayingSth();
+ const bool isPlaying = aSource->IsPlaying;
if (isPlaying)
{
hr = aSource->Voice->Stop();
@@ -406,7 +401,7 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
XAUDIO2_BUFFER buffer = { 0 };
buffer.pContext = aBuffer;
buffer.Flags = XAUDIO2_END_OF_STREAM;
- if (source->GetIsLooping())
+ if (loop)
buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
// Restore play position
@@ -415,7 +410,7 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
buffer.PlayLength = totalSamples - buffer.PlayBegin;
aSource->StartTimeForQueueBuffer = 0;
- XAudio2::QueueBuffer(aSource, source, bufferId, buffer);
+ XAudio2::QueueBuffer(aSource, bufferID, buffer);
if (isPlaying)
{
@@ -424,48 +419,22 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
}
}
-void AudioBackendXAudio2::Source_SpatialSetupChanged(AudioSource* source)
+void AudioBackendXAudio2::Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- aSource->Is3D = source->Is3D();
- aSource->MinDistance = source->GetMinDistance();
- aSource->Attenuation = source->GetAttenuation();
- aSource->DopplerFactor = source->GetDopplerFactor();
+ aSource->Is3D = spatial;
+ aSource->MinDistance = minDistance;
+ aSource->Attenuation = attenuation;
+ aSource->DopplerFactor = doppler;
aSource->IsDirty = true;
}
}
-void AudioBackendXAudio2::Source_ClipLoaded(AudioSource* source)
+void AudioBackendXAudio2::Source_Play(uint32 sourceID)
{
- ScopeLock lock(XAudio2::Locker);
- auto aSource = XAudio2::GetSource(source);
- if (!aSource)
- {
- // Register source if clip was missing
- Source_OnAdd(source);
- }
-}
-
-void AudioBackendXAudio2::Source_Cleanup(AudioSource* source)
-{
- ScopeLock lock(XAudio2::Locker);
- auto aSource = XAudio2::GetSource(source);
- if (!aSource)
- return;
-
- // Free source
- if (aSource->Voice)
- {
- aSource->Voice->DestroyVoice();
- }
- aSource->Init();
-}
-
-void AudioBackendXAudio2::Source_Play(AudioSource* source)
-{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice && !aSource->IsPlaying)
{
// Play
@@ -475,9 +444,9 @@ void AudioBackendXAudio2::Source_Play(AudioSource* source)
}
}
-void AudioBackendXAudio2::Source_Pause(AudioSource* source)
+void AudioBackendXAudio2::Source_Pause(uint32 sourceID)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice && aSource->IsPlaying)
{
// Pause
@@ -487,9 +456,9 @@ void AudioBackendXAudio2::Source_Pause(AudioSource* source)
}
}
-void AudioBackendXAudio2::Source_Stop(AudioSource* source)
+void AudioBackendXAudio2::Source_Stop(uint32 sourceID)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice)
{
aSource->StartTimeForQueueBuffer = 0.0f;
@@ -509,9 +478,9 @@ void AudioBackendXAudio2::Source_Stop(AudioSource* source)
}
}
-void AudioBackendXAudio2::Source_SetCurrentBufferTime(AudioSource* source, float value)
+void AudioBackendXAudio2::Source_SetCurrentBufferTime(uint32 sourceID, float value)
{
- const auto aSource = XAudio2::GetSource(source);
+ const auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
// Store start time so next buffer submitted will start from here (assumes audio is stopped)
@@ -519,60 +488,63 @@ void AudioBackendXAudio2::Source_SetCurrentBufferTime(AudioSource* source, float
}
}
-float AudioBackendXAudio2::Source_GetCurrentBufferTime(const AudioSource* source)
+float AudioBackendXAudio2::Source_GetCurrentBufferTime(uint32 sourceID)
{
float time = 0;
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource)
{
- ASSERT(source->Clip && source->Clip->IsLoaded());
- const auto& clipInfo = source->Clip->AudioHeader.Info;
+ const auto& clipInfo = aSource->Info;
XAUDIO2_VOICE_STATE state;
aSource->Voice->GetState(&state);
- const uint32 numChannels = clipInfo.NumChannels;
- const uint32 totalSamples = clipInfo.NumSamples / numChannels;
+ const uint32 totalSamples = clipInfo.NumSamples / clipInfo.NumChannels;
const uint32 sampleRate = clipInfo.SampleRate; // / clipInfo.NumChannels;
- state.SamplesPlayed -= aSource->LastBufferStartSamplesPlayed % totalSamples; // Offset by the last buffer start to get time relative to its begin
- time = aSource->LastBufferStartTime + (state.SamplesPlayed % totalSamples) / static_cast(Math::Max(1U, sampleRate));
+ uint64 lastBufferStartSamplesPlayed = aSource->LastBufferStartSamplesPlayed;
+ if (totalSamples > 0)
+ lastBufferStartSamplesPlayed %= totalSamples;
+ state.SamplesPlayed -= lastBufferStartSamplesPlayed % totalSamples; // Offset by the last buffer start to get time relative to its begin
+ if (totalSamples > 0)
+ state.SamplesPlayed %= totalSamples;
+ time = aSource->LastBufferStartTime + state.SamplesPlayed / static_cast(Math::Max(1U, sampleRate));
}
return time;
}
-void AudioBackendXAudio2::Source_SetNonStreamingBuffer(AudioSource* source)
+void AudioBackendXAudio2::Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (!aSource)
return;
+ aSource->LastBufferID = bufferID; // Use for looping change
XAudio2::Locker.Lock();
- const uint32 bufferId = source->Clip->Buffers[0];
- XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
+ XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferID - 1];
XAudio2::Locker.Unlock();
XAUDIO2_BUFFER buffer = { 0 };
buffer.pContext = aBuffer;
buffer.Flags = XAUDIO2_END_OF_STREAM;
- if (source->GetIsLooping())
+ if (aSource->IsLoop)
buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
// Queue single buffer
- XAudio2::QueueBuffer(aSource, source, bufferId, buffer);
+ XAudio2::QueueBuffer(aSource, bufferID, buffer);
}
-void AudioBackendXAudio2::Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount)
+void AudioBackendXAudio2::Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount)
{
processedBuffersCount = 0;
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice)
{
processedBuffersCount = aSource->BuffersProcessed;
}
}
-void AudioBackendXAudio2::Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount)
+void AudioBackendXAudio2::Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount)
{
queuedBuffersCount = 0;
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice)
{
XAUDIO2_VOICE_STATE state;
@@ -581,23 +553,24 @@ void AudioBackendXAudio2::Source_GetQueuedBuffersCount(AudioSource* source, int3
}
}
-void AudioBackendXAudio2::Source_QueueBuffer(AudioSource* source, uint32 bufferId)
+void AudioBackendXAudio2::Source_QueueBuffer(uint32 sourceID, uint32 bufferID)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (!aSource)
return;
+ aSource->LastBufferID = bufferID; // Use for looping change
- XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
+ XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferID - 1];
XAUDIO2_BUFFER buffer = { 0 };
buffer.pContext = aBuffer;
- XAudio2::QueueBuffer(aSource, source, bufferId, buffer);
+ XAudio2::QueueBuffer(aSource, bufferID, buffer);
}
-void AudioBackendXAudio2::Source_DequeueProcessedBuffers(AudioSource* source)
+void AudioBackendXAudio2::Source_DequeueProcessedBuffers(uint32 sourceID)
{
- auto aSource = XAudio2::GetSource(source);
+ auto aSource = XAudio2::GetSource(sourceID);
if (aSource && aSource->Voice)
{
const HRESULT hr = aSource->Voice->FlushSourceBuffers();
@@ -608,7 +581,7 @@ void AudioBackendXAudio2::Source_DequeueProcessedBuffers(AudioSource* source)
uint32 AudioBackendXAudio2::Buffer_Create()
{
- uint32 bufferId;
+ uint32 bufferID;
ScopeLock lock(XAudio2::Locker);
// Get first free buffer slot
@@ -619,7 +592,7 @@ uint32 AudioBackendXAudio2::Buffer_Create()
{
aBuffer = New();
XAudio2::Buffers[i] = aBuffer;
- bufferId = i + 1;
+ bufferID = i + 1;
break;
}
}
@@ -628,28 +601,28 @@ uint32 AudioBackendXAudio2::Buffer_Create()
// Add new slot
aBuffer = New();
XAudio2::Buffers.Add(aBuffer);
- bufferId = XAudio2::Buffers.Count();
+ bufferID = XAudio2::Buffers.Count();
}
aBuffer->Data.Resize(0);
- return bufferId;
+ return bufferID;
}
-void AudioBackendXAudio2::Buffer_Delete(uint32 bufferId)
+void AudioBackendXAudio2::Buffer_Delete(uint32 bufferID)
{
ScopeLock lock(XAudio2::Locker);
- XAudio2::Buffer*& aBuffer = XAudio2::Buffers[bufferId - 1];
+ XAudio2::Buffer*& aBuffer = XAudio2::Buffers[bufferID - 1];
aBuffer->Data.Resize(0);
Delete(aBuffer);
aBuffer = nullptr;
}
-void AudioBackendXAudio2::Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info)
+void AudioBackendXAudio2::Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info)
{
CHECK(info.NumChannels <= MAX_INPUT_CHANNELS);
XAudio2::Locker.Lock();
- XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
+ XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferID - 1];
XAudio2::Locker.Unlock();
const uint32 samplesLength = info.NumSamples * info.BitDepth / 8;
@@ -735,7 +708,6 @@ bool AudioBackendXAudio2::Base_Init()
void AudioBackendXAudio2::Base_Update()
{
// Update dirty voices
- const auto listener = XAudio2::GetListener();
float outputMatrix[MAX_CHANNELS_MATRIX_SIZE];
for (int32 i = 0; i < XAudio2::Sources.Count(); i++)
{
@@ -743,7 +715,7 @@ void AudioBackendXAudio2::Base_Update()
if (source.IsFree() || !(source.IsDirty || XAudio2::ForceDirty))
continue;
- auto mix = AudioBackendTools::CalculateSoundMix(XAudio2::Settings, *listener, source, XAudio2::Channels);
+ auto mix = AudioBackendTools::CalculateSoundMix(XAudio2::Settings, XAudio2::Listener, source, XAudio2::Channels);
mix.VolumeIntoChannels();
AudioBackendTools::MapChannels(source.Channels, XAudio2::Channels, mix.Channels, outputMatrix);
diff --git a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h
index 073dbfdc3..56c79bb69 100644
--- a/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h
+++ b/Source/Engine/Audio/XAudio2/AudioBackendXAudio2.h
@@ -17,30 +17,28 @@ public:
void Listener_VelocityChanged(const Vector3& velocity) override;
void Listener_TransformChanged(const Vector3& position, const Quaternion& orientation) override;
void Listener_ReinitializeAll() override;
- void Source_OnAdd(AudioSource* source) override;
- void Source_OnRemove(AudioSource* source) override;
- void Source_VelocityChanged(AudioSource* source) override;
- void Source_TransformChanged(AudioSource* source) override;
- void Source_VolumeChanged(AudioSource* source) override;
- void Source_PitchChanged(AudioSource* source) override;
- void Source_PanChanged(AudioSource* source) override;
- void Source_IsLoopingChanged(AudioSource* source) override;
- void Source_SpatialSetupChanged(AudioSource* source) override;
- void Source_ClipLoaded(AudioSource* source) override;
- void Source_Cleanup(AudioSource* source) override;
- void Source_Play(AudioSource* source) override;
- void Source_Pause(AudioSource* source) override;
- void Source_Stop(AudioSource* source) override;
- void Source_SetCurrentBufferTime(AudioSource* source, float value) override;
- float Source_GetCurrentBufferTime(const AudioSource* source) override;
- void Source_SetNonStreamingBuffer(AudioSource* source) override;
- void Source_GetProcessedBuffersCount(AudioSource* source, int32& processedBuffersCount) override;
- void Source_GetQueuedBuffersCount(AudioSource* source, int32& queuedBuffersCount) override;
- void Source_QueueBuffer(AudioSource* source, uint32 bufferId) override;
- void Source_DequeueProcessedBuffers(AudioSource* source) override;
+ uint32 Source_Add(const AudioDataInfo& format, const Vector3& position, const Quaternion& orientation, float volume, float pitch, float pan, bool loop, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Remove(uint32 sourceID) override;
+ void Source_VelocityChanged(uint32 sourceID, const Vector3& velocity) override;
+ void Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation) override;
+ void Source_VolumeChanged(uint32 sourceID, float volume) override;
+ void Source_PitchChanged(uint32 sourceID, float pitch) override;
+ void Source_PanChanged(uint32 sourceID, float pan) override;
+ void Source_IsLoopingChanged(uint32 sourceID, bool loop) override;
+ void Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler) override;
+ void Source_Play(uint32 sourceID) override;
+ void Source_Pause(uint32 sourceID) override;
+ void Source_Stop(uint32 sourceID) override;
+ void Source_SetCurrentBufferTime(uint32 sourceID, float value) override;
+ float Source_GetCurrentBufferTime(uint32 sourceID) override;
+ void Source_SetNonStreamingBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_GetProcessedBuffersCount(uint32 sourceID, int32& processedBuffersCount) override;
+ void Source_GetQueuedBuffersCount(uint32 sourceID, int32& queuedBuffersCount) override;
+ void Source_QueueBuffer(uint32 sourceID, uint32 bufferID) override;
+ void Source_DequeueProcessedBuffers(uint32 sourceID) override;
uint32 Buffer_Create() override;
- void Buffer_Delete(uint32 bufferId) override;
- void Buffer_Write(uint32 bufferId, byte* samples, const AudioDataInfo& info) override;
+ void Buffer_Delete(uint32 bufferID) override;
+ void Buffer_Write(uint32 bufferID, byte* samples, const AudioDataInfo& info) override;
const Char* Base_Name() override;
FeatureFlags Base_Features() override;
void Base_OnActiveDeviceChanged() override;