diff --git a/include/Nazara/Audio/AudioBuffer.hpp b/include/Nazara/Audio/AudioBuffer.hpp index ea3de270d..aa35de110 100644 --- a/include/Nazara/Audio/AudioBuffer.hpp +++ b/include/Nazara/Audio/AudioBuffer.hpp @@ -29,6 +29,8 @@ namespace Nz virtual UInt32 GetSize() const = 0; virtual UInt32 GetSampleRate() const = 0; + virtual bool IsCompatibleWith(const AudioDevice& device) const = 0; + virtual bool Reset(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const void* samples) = 0; AudioBuffer& operator=(const AudioBuffer&) = default; diff --git a/include/Nazara/Audio/AudioDevice.hpp b/include/Nazara/Audio/AudioDevice.hpp index 4535b8466..f815f10b9 100644 --- a/include/Nazara/Audio/AudioDevice.hpp +++ b/include/Nazara/Audio/AudioDevice.hpp @@ -38,6 +38,7 @@ namespace Nz virtual Quaternionf GetListenerRotation() const = 0; virtual Vector3f GetListenerVelocity() const = 0; virtual float GetSpeedOfSound() const = 0; + virtual const void* GetSubSystemIdentifier() const = 0; virtual bool IsFormatSupported(AudioFormat format) const = 0; diff --git a/include/Nazara/Audio/OpenALBuffer.hpp b/include/Nazara/Audio/OpenALBuffer.hpp index a114eb7b3..af1861b11 100644 --- a/include/Nazara/Audio/OpenALBuffer.hpp +++ b/include/Nazara/Audio/OpenALBuffer.hpp @@ -32,6 +32,8 @@ namespace Nz UInt32 GetSize() const override; UInt32 GetSampleRate() const override; + bool IsCompatibleWith(const AudioDevice& device) const override; + bool Reset(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const void* samples) override; OpenALBuffer& operator=(const OpenALBuffer&) = delete; diff --git a/include/Nazara/Audio/OpenALDevice.hpp b/include/Nazara/Audio/OpenALDevice.hpp index ba2331f1e..612a29921 100644 --- a/include/Nazara/Audio/OpenALDevice.hpp +++ b/include/Nazara/Audio/OpenALDevice.hpp @@ -39,9 +39,10 @@ namespace Nz float GetGlobalVolume() const override; Vector3f GetListenerDirection(Vector3f* up = nullptr) const override; Vector3f GetListenerPosition() const override; - Quaternionf GetListenerRotation(Vector3f* up = nullptr) const override; + Quaternionf GetListenerRotation() const override; Vector3f GetListenerVelocity() const override; float GetSpeedOfSound() const override; + const void* GetSubSystemIdentifier() const override; bool IsFormatSupported(AudioFormat format) const override; diff --git a/include/Nazara/Audio/SoundBuffer.hpp b/include/Nazara/Audio/SoundBuffer.hpp index d3b2c571a..ba45b0423 100644 --- a/include/Nazara/Audio/SoundBuffer.hpp +++ b/include/Nazara/Audio/SoundBuffer.hpp @@ -50,7 +50,7 @@ namespace Nz SoundBuffer(SoundBuffer&&) = delete; ~SoundBuffer() = default; - const std::shared_ptr& GetBuffer(AudioDevice* device); + const std::shared_ptr& GetAudioBuffer(AudioDevice* device); inline UInt32 GetDuration() const; inline AudioFormat GetFormat() const; diff --git a/src/Nazara/Audio/OpenALBuffer.cpp b/src/Nazara/Audio/OpenALBuffer.cpp index c7c2cefcd..90d108673 100644 --- a/src/Nazara/Audio/OpenALBuffer.cpp +++ b/src/Nazara/Audio/OpenALBuffer.cpp @@ -52,6 +52,12 @@ namespace Nz return SafeCast(sampleRate); } + bool OpenALBuffer::IsCompatibleWith(const AudioDevice& device) const + { + // OpenAL buffers are shared among contexts and thus devices + return device.GetSubSystemIdentifier() == &m_library; + } + bool OpenALBuffer::Reset(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const void* samples) { OpenALDevice& device = GetDevice(); diff --git a/src/Nazara/Audio/OpenALDevice.cpp b/src/Nazara/Audio/OpenALDevice.cpp index 1443633bf..1ac5fce2b 100644 --- a/src/Nazara/Audio/OpenALDevice.cpp +++ b/src/Nazara/Audio/OpenALDevice.cpp @@ -206,6 +206,11 @@ namespace Nz return m_library.alGetFloat(AL_SPEED_OF_SOUND); } + const void* OpenALDevice::GetSubSystemIdentifier() const + { + return &m_library; + } + /*! * \brief Checks whether the format is supported by the engine * \return true if it is the case diff --git a/src/Nazara/Audio/OpenALSource.cpp b/src/Nazara/Audio/OpenALSource.cpp index 003e8007f..44b1f98d3 100644 --- a/src/Nazara/Audio/OpenALSource.cpp +++ b/src/Nazara/Audio/OpenALSource.cpp @@ -150,7 +150,7 @@ namespace Nz void OpenALSource::QueueBuffer(std::shared_ptr audioBuffer) { NazaraAssert(audioBuffer, "invalid buffer"); - NazaraAssert(audioBuffer->GetAudioDevice() == GetAudioDevice(), "incompatible buffer"); + NazaraAssert(audioBuffer->IsCompatibleWith(*GetAudioDevice()), "incompatible buffer"); std::shared_ptr newBuffer = std::static_pointer_cast(std::move(audioBuffer)); @@ -185,7 +185,7 @@ namespace Nz void OpenALSource::SetBuffer(std::shared_ptr audioBuffer) { - NazaraAssert(audioBuffer->GetAudioDevice() == GetAudioDevice(), "incompatible buffer"); + NazaraAssert(audioBuffer->IsCompatibleWith(*GetAudioDevice()), "incompatible buffer"); std::shared_ptr newBuffer = std::static_pointer_cast(std::move(audioBuffer)); diff --git a/src/Nazara/Audio/Sound.cpp b/src/Nazara/Audio/Sound.cpp index 2d566bb7c..b67eb854f 100644 --- a/src/Nazara/Audio/Sound.cpp +++ b/src/Nazara/Audio/Sound.cpp @@ -219,7 +219,7 @@ namespace Nz Stop(); m_buffer = std::move(buffer); - m_source->SetBuffer(m_buffer->GetBuffer(m_source->GetAudioDevice().get())); + m_source->SetBuffer(m_buffer->GetAudioBuffer(m_source->GetAudioDevice().get())); } /*! diff --git a/src/Nazara/Audio/SoundBuffer.cpp b/src/Nazara/Audio/SoundBuffer.cpp index 4272d0578..f214351c6 100644 --- a/src/Nazara/Audio/SoundBuffer.cpp +++ b/src/Nazara/Audio/SoundBuffer.cpp @@ -58,14 +58,32 @@ namespace Nz std::memcpy(&m_samples[0], samples, sampleCount * sizeof(Int16)); } - const std::shared_ptr& SoundBuffer::GetBuffer(AudioDevice* device) + const std::shared_ptr& SoundBuffer::GetAudioBuffer(AudioDevice* device) { + NazaraAssert(device, "invalid device"); + auto it = m_audioBufferByDevice.find(device); if (it == m_audioBufferByDevice.end()) { - auto audioBuffer = device->CreateBuffer(); - if (!audioBuffer->Reset(m_format, m_sampleCount, m_sampleRate, m_samples.get())) - throw std::runtime_error("failed to initialize audio buffer"); + // Try to find an existing compatible buffer + std::shared_ptr audioBuffer; + for (it = m_audioBufferByDevice.begin(); it != m_audioBufferByDevice.end(); ++it) + { + const auto& entry = it->second; + if (entry.audioBuffer->IsCompatibleWith(*device)) + { + audioBuffer = entry.audioBuffer; + break; + } + } + + if (!audioBuffer) + { + // Create a new buffer + audioBuffer = device->CreateBuffer(); + if (!audioBuffer->Reset(m_format, m_sampleCount, m_sampleRate, m_samples.get())) + throw std::runtime_error("failed to initialize audio buffer"); + } it = m_audioBufferByDevice.emplace(device, AudioDeviceEntry{}).first;