mirror of
https://github.com/SFML/SFML.git
synced 2025-02-16 21:38:00 +08:00
Add move semantics to 'SoundBuffer'
This commit is contained in:
parent
8a11078075
commit
b2644e5c3f
@ -35,6 +35,70 @@
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace sf::priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Represents unique ownership of an OpenAL buffer id
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_AUDIO_API UniqueOpenALBufferId
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~UniqueOpenALBufferId();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Move constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId(UniqueOpenALBufferId&& other) noexcept;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Move assignment
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId& operator=(UniqueOpenALBufferId&& other) noexcept;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the internal buffer id
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] unsigned int get() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Generate a new buffer
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] static UniqueOpenALBufferId generate();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the null buffer id
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] static UniqueOpenALBufferId null();
|
||||
|
||||
private:
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
static constexpr unsigned int NullBufferId = 0u;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from an existing buffer identifier
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit UniqueOpenALBufferId(unsigned int bufferId);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int m_bufferId; //!< OpenAL buffer identifier
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -64,6 +128,14 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer(const SoundBuffer& copy);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Move constructor
|
||||
///
|
||||
/// \param other Instance to move
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer(SoundBuffer&& move) noexcept;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
@ -214,7 +286,7 @@ public:
|
||||
Time getDuration() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of assignment operator
|
||||
/// \brief Overload of copy assignment operator
|
||||
///
|
||||
/// \param right Instance to assign
|
||||
///
|
||||
@ -223,6 +295,16 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& operator =(const SoundBuffer& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of move assignment operator
|
||||
///
|
||||
/// \param right Instance to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& operator =(SoundBuffer&& right) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
friend class Sound;
|
||||
@ -267,15 +349,15 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
using SoundList = std::unordered_set<Sound *>; //!< Set of unique sound instances
|
||||
using SoundList = std::unordered_set<Sound*>; //!< Set of unique sound instances
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int m_buffer; //!< OpenAL buffer identifier
|
||||
std::vector<Int16> m_samples; //!< Samples buffer
|
||||
Time m_duration; //!< Sound duration
|
||||
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
||||
priv::UniqueOpenALBufferId m_uniqueBufferId; //!< OpenAL buffer identifier
|
||||
std::vector<Int16> m_samples; //!< Samples buffer
|
||||
Time m_duration; //!< Sound duration
|
||||
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__clang__)
|
||||
@ -43,34 +44,96 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace sf::priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId::UniqueOpenALBufferId(unsigned int bufferId) :
|
||||
m_bufferId(bufferId)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId::~UniqueOpenALBufferId()
|
||||
{
|
||||
// Destroy the buffer
|
||||
if (m_bufferId != NullBufferId)
|
||||
alCheck(alDeleteBuffers(1, &m_bufferId));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId::UniqueOpenALBufferId(UniqueOpenALBufferId&& other) noexcept :
|
||||
m_bufferId(std::exchange(other.m_bufferId, NullBufferId))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
UniqueOpenALBufferId& UniqueOpenALBufferId::operator=(UniqueOpenALBufferId&& other) noexcept
|
||||
{
|
||||
m_bufferId = std::exchange(other.m_bufferId, NullBufferId);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] unsigned int UniqueOpenALBufferId::get() const
|
||||
{
|
||||
return m_bufferId;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] UniqueOpenALBufferId UniqueOpenALBufferId::generate()
|
||||
{
|
||||
// Create the buffer
|
||||
unsigned int bufferId;
|
||||
alCheck(alGenBuffers(1, &bufferId));
|
||||
|
||||
return UniqueOpenALBufferId(bufferId);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] UniqueOpenALBufferId UniqueOpenALBufferId::null()
|
||||
{
|
||||
return UniqueOpenALBufferId(NullBufferId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer() :
|
||||
m_buffer (0),
|
||||
m_duration()
|
||||
AlResource (),
|
||||
m_uniqueBufferId(priv::UniqueOpenALBufferId::generate()),
|
||||
m_samples (),
|
||||
m_duration (),
|
||||
m_sounds ()
|
||||
{
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
|
||||
m_buffer (0),
|
||||
m_samples (copy.m_samples),
|
||||
m_duration(copy.m_duration),
|
||||
m_sounds () // don't copy the attached sounds
|
||||
AlResource (copy),
|
||||
m_uniqueBufferId(priv::UniqueOpenALBufferId::generate()),
|
||||
m_samples (copy.m_samples),
|
||||
m_duration (copy.m_duration),
|
||||
m_sounds () // don't copy the attached sounds
|
||||
{
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
if (!update(copy.getChannelCount(), copy.getSampleRate()))
|
||||
err() << "Failed to update copy-constructed sound buffer" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer(SoundBuffer&& move) noexcept = default;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::~SoundBuffer()
|
||||
{
|
||||
@ -83,10 +146,6 @@ SoundBuffer::~SoundBuffer()
|
||||
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||
for (Sound* soundPtr : sounds)
|
||||
soundPtr->resetBuffer();
|
||||
|
||||
// Destroy the buffer
|
||||
if (m_buffer)
|
||||
alCheck(alDeleteBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
@ -186,7 +245,7 @@ Uint64 SoundBuffer::getSampleCount() const
|
||||
unsigned int SoundBuffer::getSampleRate() const
|
||||
{
|
||||
ALint sampleRate;
|
||||
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
|
||||
alCheck(alGetBufferi(m_uniqueBufferId.get(), AL_FREQUENCY, &sampleRate));
|
||||
|
||||
return static_cast<unsigned int>(sampleRate);
|
||||
}
|
||||
@ -196,7 +255,7 @@ unsigned int SoundBuffer::getSampleRate() const
|
||||
unsigned int SoundBuffer::getChannelCount() const
|
||||
{
|
||||
ALint channelCount;
|
||||
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
|
||||
alCheck(alGetBufferi(m_uniqueBufferId.get(), AL_CHANNELS, &channelCount));
|
||||
|
||||
return static_cast<unsigned int>(channelCount);
|
||||
}
|
||||
@ -212,12 +271,34 @@ Time SoundBuffer::getDuration() const
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
||||
{
|
||||
if (&right == this)
|
||||
return *this;
|
||||
|
||||
AlResource::operator=(right);
|
||||
|
||||
SoundBuffer temp(right);
|
||||
|
||||
std::swap(m_samples, temp.m_samples);
|
||||
std::swap(m_buffer, temp.m_buffer);
|
||||
std::swap(m_duration, temp.m_duration);
|
||||
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
|
||||
std::swap(m_samples, temp.m_samples);
|
||||
std::swap(m_uniqueBufferId, temp.m_uniqueBufferId);
|
||||
std::swap(m_duration, temp.m_duration);
|
||||
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& SoundBuffer::operator =(SoundBuffer&& right) noexcept
|
||||
{
|
||||
if (&right == this)
|
||||
return *this;
|
||||
|
||||
AlResource::operator=(std::move(right));
|
||||
|
||||
m_uniqueBufferId = std::move(right.m_uniqueBufferId);
|
||||
m_samples = std::move(right.m_samples);
|
||||
m_duration = std::move(right.m_duration);
|
||||
m_sounds = std::move(right.m_sounds);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -270,8 +351,8 @@ bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
|
||||
soundPtr->resetBuffer();
|
||||
|
||||
// Fill the buffer
|
||||
auto size = static_cast<ALsizei>(m_samples.size() * sizeof(Int16));
|
||||
alCheck(alBufferData(m_buffer, format, m_samples.data(), size, static_cast<ALsizei>(sampleRate)));
|
||||
const auto size = static_cast<ALsizei>(m_samples.size() * sizeof(Int16));
|
||||
alCheck(alBufferData(m_uniqueBufferId.get(), format, m_samples.data(), size, static_cast<ALsizei>(sampleRate)));
|
||||
|
||||
// Compute the duration
|
||||
m_duration = seconds(static_cast<float>(m_samples.size()) / static_cast<float>(sampleRate) / static_cast<float>(channelCount));
|
||||
|
Loading…
x
Reference in New Issue
Block a user