mirror of
https://github.com/SFML/SFML.git
synced 2025-02-19 06:39:59 +08:00
Add move semantics to 'SoundBuffer'
This commit is contained in:
parent
8a11078075
commit
b2644e5c3f
@ -35,6 +35,70 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_set>
|
#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
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -64,6 +128,14 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer(const SoundBuffer& copy);
|
SoundBuffer(const SoundBuffer& copy);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Move constructor
|
||||||
|
///
|
||||||
|
/// \param other Instance to move
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer(SoundBuffer&& move) noexcept;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
///
|
///
|
||||||
@ -214,7 +286,7 @@ public:
|
|||||||
Time getDuration() const;
|
Time getDuration() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Overload of assignment operator
|
/// \brief Overload of copy assignment operator
|
||||||
///
|
///
|
||||||
/// \param right Instance to assign
|
/// \param right Instance to assign
|
||||||
///
|
///
|
||||||
@ -223,6 +295,16 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer& operator =(const SoundBuffer& right);
|
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:
|
private:
|
||||||
|
|
||||||
friend class Sound;
|
friend class Sound;
|
||||||
@ -267,15 +349,15 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Types
|
// 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
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int m_buffer; //!< OpenAL buffer identifier
|
priv::UniqueOpenALBufferId m_uniqueBufferId; //!< OpenAL buffer identifier
|
||||||
std::vector<Int16> m_samples; //!< Samples buffer
|
std::vector<Int16> m_samples; //!< Samples buffer
|
||||||
Time m_duration; //!< Sound duration
|
Time m_duration; //!< Sound duration
|
||||||
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
mutable SoundList m_sounds; //!< List of sounds that are using this buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
@ -43,34 +44,96 @@
|
|||||||
#endif
|
#endif
|
||||||
#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
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::SoundBuffer() :
|
SoundBuffer::SoundBuffer() :
|
||||||
m_buffer (0),
|
AlResource (),
|
||||||
m_duration()
|
m_uniqueBufferId(priv::UniqueOpenALBufferId::generate()),
|
||||||
|
m_samples (),
|
||||||
|
m_duration (),
|
||||||
|
m_sounds ()
|
||||||
{
|
{
|
||||||
// Create the buffer
|
|
||||||
alCheck(alGenBuffers(1, &m_buffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
|
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
|
||||||
m_buffer (0),
|
AlResource (copy),
|
||||||
m_samples (copy.m_samples),
|
m_uniqueBufferId(priv::UniqueOpenALBufferId::generate()),
|
||||||
m_duration(copy.m_duration),
|
m_samples (copy.m_samples),
|
||||||
m_sounds () // don't copy the attached sounds
|
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
|
// Update the internal buffer with the new samples
|
||||||
if (!update(copy.getChannelCount(), copy.getSampleRate()))
|
if (!update(copy.getChannelCount(), copy.getSampleRate()))
|
||||||
err() << "Failed to update copy-constructed sound buffer" << std::endl;
|
err() << "Failed to update copy-constructed sound buffer" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundBuffer::SoundBuffer(SoundBuffer&& move) noexcept = default;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer::~SoundBuffer()
|
SoundBuffer::~SoundBuffer()
|
||||||
{
|
{
|
||||||
@ -83,10 +146,6 @@ SoundBuffer::~SoundBuffer()
|
|||||||
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||||
for (Sound* soundPtr : sounds)
|
for (Sound* soundPtr : sounds)
|
||||||
soundPtr->resetBuffer();
|
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
|
unsigned int SoundBuffer::getSampleRate() const
|
||||||
{
|
{
|
||||||
ALint sampleRate;
|
ALint sampleRate;
|
||||||
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
|
alCheck(alGetBufferi(m_uniqueBufferId.get(), AL_FREQUENCY, &sampleRate));
|
||||||
|
|
||||||
return static_cast<unsigned int>(sampleRate);
|
return static_cast<unsigned int>(sampleRate);
|
||||||
}
|
}
|
||||||
@ -196,7 +255,7 @@ unsigned int SoundBuffer::getSampleRate() const
|
|||||||
unsigned int SoundBuffer::getChannelCount() const
|
unsigned int SoundBuffer::getChannelCount() const
|
||||||
{
|
{
|
||||||
ALint channelCount;
|
ALint channelCount;
|
||||||
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
|
alCheck(alGetBufferi(m_uniqueBufferId.get(), AL_CHANNELS, &channelCount));
|
||||||
|
|
||||||
return static_cast<unsigned int>(channelCount);
|
return static_cast<unsigned int>(channelCount);
|
||||||
}
|
}
|
||||||
@ -212,12 +271,34 @@ Time SoundBuffer::getDuration() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
||||||
{
|
{
|
||||||
|
if (&right == this)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
AlResource::operator=(right);
|
||||||
|
|
||||||
SoundBuffer temp(right);
|
SoundBuffer temp(right);
|
||||||
|
|
||||||
std::swap(m_samples, temp.m_samples);
|
std::swap(m_samples, temp.m_samples);
|
||||||
std::swap(m_buffer, temp.m_buffer);
|
std::swap(m_uniqueBufferId, temp.m_uniqueBufferId);
|
||||||
std::swap(m_duration, temp.m_duration);
|
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_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;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -270,8 +351,8 @@ bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
|
|||||||
soundPtr->resetBuffer();
|
soundPtr->resetBuffer();
|
||||||
|
|
||||||
// Fill the buffer
|
// Fill the buffer
|
||||||
auto size = static_cast<ALsizei>(m_samples.size() * sizeof(Int16));
|
const auto size = static_cast<ALsizei>(m_samples.size() * sizeof(Int16));
|
||||||
alCheck(alBufferData(m_buffer, format, m_samples.data(), size, static_cast<ALsizei>(sampleRate)));
|
alCheck(alBufferData(m_uniqueBufferId.get(), format, m_samples.data(), size, static_cast<ALsizei>(sampleRate)));
|
||||||
|
|
||||||
// Compute the duration
|
// Compute the duration
|
||||||
m_duration = seconds(static_cast<float>(m_samples.size()) / static_cast<float>(sampleRate) / static_cast<float>(channelCount));
|
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