Audio: Make Music, Sound, SoundEmitter movable

This commit is contained in:
Lynix 2018-04-08 17:51:25 +02:00
parent 31fc8c9dad
commit 3c4c0fab66
7 changed files with 104 additions and 18 deletions

View File

@ -81,6 +81,7 @@ Nazara Engine:
- Fixed IPv6 addresses not being correctly encoded/decoded from the socket API. - Fixed IPv6 addresses not being correctly encoded/decoded from the socket API.
- Fix copy and move semantic on HandledObject and ObjectHandle - Fix copy and move semantic on HandledObject and ObjectHandle
- Add support for emissive and normal maps in .mtl loader using custom keywords ([map_]emissive and [map_]normal) - Add support for emissive and normal maps in .mtl loader using custom keywords ([map_]emissive and [map_]normal)
- Music, Sound and SoundEmitter are now movable
Nazara Development Kit: Nazara Development Kit:
- Added ImageWidget (#139) - Added ImageWidget (#139)

View File

@ -38,7 +38,7 @@ namespace Nz
public: public:
Music() = default; Music() = default;
Music(const Music&) = delete; Music(const Music&) = delete;
Music(Music&&) = delete; Music(Music&&) noexcept = default;
~Music(); ~Music();
bool Create(SoundStream* soundStream); bool Create(SoundStream* soundStream);
@ -67,10 +67,10 @@ namespace Nz
void Stop() override; void Stop() override;
Music& operator=(const Music&) = delete; Music& operator=(const Music&) = delete;
Music& operator=(Music&&) = delete; Music& operator=(Music&&) noexcept = default;
private: private:
MovablePtr<MusicImpl> m_impl = nullptr; MovablePtr<MusicImpl> m_impl;
bool FillAndQueueBuffer(unsigned int buffer); bool FillAndQueueBuffer(unsigned int buffer);
void MusicThread(); void MusicThread();

View File

@ -20,7 +20,7 @@ namespace Nz
Sound() = default; Sound() = default;
Sound(const SoundBuffer* soundBuffer); Sound(const SoundBuffer* soundBuffer);
Sound(const Sound& sound); Sound(const Sound& sound);
Sound(Sound&&) = default; Sound(Sound&&) noexcept = default;
~Sound(); ~Sound();
void EnableLooping(bool loop) override; void EnableLooping(bool loop) override;
@ -47,7 +47,7 @@ namespace Nz
void Stop() override; void Stop() override;
Sound& operator=(const Sound&) = delete; ///TODO? Sound& operator=(const Sound&) = delete; ///TODO?
Sound& operator=(Sound&&) = default; Sound& operator=(Sound&&) noexcept = default;
private: private:
SoundBufferConstRef m_buffer; SoundBufferConstRef m_buffer;

View File

@ -11,6 +11,7 @@
#include <Nazara/Audio/Config.hpp> #include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp> #include <Nazara/Audio/Enums.hpp>
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
#include <limits>
///TODO: Inherit SoundEmitter from Node ///TODO: Inherit SoundEmitter from Node
@ -19,6 +20,7 @@ namespace Nz
class NAZARA_AUDIO_API SoundEmitter class NAZARA_AUDIO_API SoundEmitter
{ {
public: public:
SoundEmitter(SoundEmitter&& emitter) noexcept;
virtual ~SoundEmitter(); virtual ~SoundEmitter();
virtual void EnableLooping(bool loop) = 0; virtual void EnableLooping(bool loop) = 0;
@ -51,16 +53,17 @@ namespace Nz
virtual void Stop() = 0; virtual void Stop() = 0;
SoundEmitter& operator=(const SoundEmitter&) = delete; ///TODO SoundEmitter& operator=(const SoundEmitter&) = delete;
SoundEmitter& operator=(SoundEmitter&&) = delete; SoundEmitter& operator=(SoundEmitter&&) noexcept;
protected: protected:
SoundEmitter(); SoundEmitter();
SoundEmitter(const SoundEmitter& emitter); SoundEmitter(const SoundEmitter& emitter);
SoundEmitter(SoundEmitter&&) = delete;
SoundStatus GetInternalStatus() const; SoundStatus GetInternalStatus() const;
static constexpr unsigned int InvalidSource = std::numeric_limits<unsigned int>::max();
unsigned int m_source; unsigned int m_source;
}; };
} }

View File

@ -262,6 +262,8 @@ namespace Nz
*/ */
void Music::Pause() void Music::Pause()
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcePause(m_source); alSourcePause(m_source);
} }

View File

@ -56,6 +56,8 @@ namespace Nz
*/ */
void Sound::EnableLooping(bool loop) void Sound::EnableLooping(bool loop)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcei(m_source, AL_LOOPING, loop); alSourcei(m_source, AL_LOOPING, loop);
} }
@ -87,6 +89,8 @@ namespace Nz
*/ */
UInt32 Sound::GetPlayingOffset() const UInt32 Sound::GetPlayingOffset() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALint samples = 0; ALint samples = 0;
alGetSourcei(m_source, AL_SAMPLE_OFFSET, &samples); alGetSourcei(m_source, AL_SAMPLE_OFFSET, &samples);
@ -108,6 +112,8 @@ namespace Nz
*/ */
bool Sound::IsLooping() const bool Sound::IsLooping() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALint loop; ALint loop;
alGetSourcei(m_source, AL_LOOPING, &loop); alGetSourcei(m_source, AL_LOOPING, &loop);
@ -205,6 +211,8 @@ namespace Nz
*/ */
void Sound::Pause() void Sound::Pause()
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcePause(m_source); alSourcePause(m_source);
} }
@ -215,6 +223,7 @@ namespace Nz
*/ */
void Sound::Play() void Sound::Play()
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
NazaraAssert(IsPlayable(), "Music is not playable"); NazaraAssert(IsPlayable(), "Music is not playable");
alSourcePlay(m_source); alSourcePlay(m_source);
@ -229,6 +238,7 @@ namespace Nz
*/ */
void Sound::SetBuffer(const SoundBuffer* buffer) void Sound::SetBuffer(const SoundBuffer* buffer)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
NazaraAssert(!buffer || buffer->IsValid(), "Invalid sound buffer"); NazaraAssert(!buffer || buffer->IsValid(), "Invalid sound buffer");
if (m_buffer == buffer) if (m_buffer == buffer)
@ -251,14 +261,19 @@ namespace Nz
*/ */
void Sound::SetPlayingOffset(UInt32 offset) void Sound::SetPlayingOffset(UInt32 offset)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcei(m_source, AL_SAMPLE_OFFSET, static_cast<ALint>(offset/1000.f * m_buffer->GetSampleRate())); alSourcei(m_source, AL_SAMPLE_OFFSET, static_cast<ALint>(offset/1000.f * m_buffer->GetSampleRate()));
} }
/*! /*!
* \brief Stops the sound * \brief Stops the sound
*
* \remark This is one of the only function that can be called on a moved sound (and does nothing)
*/ */
void Sound::Stop() void Sound::Stop()
{ {
alSourceStop(m_source); if (m_source != InvalidSource)
alSourceStop(m_source);
} }
} }

View File

@ -23,7 +23,6 @@ namespace Nz
/*! /*!
* \brief Constructs a SoundEmitter object * \brief Constructs a SoundEmitter object
*/ */
SoundEmitter::SoundEmitter() SoundEmitter::SoundEmitter()
{ {
alGenSources(1, &m_source); alGenSources(1, &m_source);
@ -39,22 +38,40 @@ namespace Nz
SoundEmitter::SoundEmitter(const SoundEmitter& emitter) SoundEmitter::SoundEmitter(const SoundEmitter& emitter)
{ {
alGenSources(1, &m_source); if (emitter.m_source != InvalidSource)
{
alGenSources(1, &m_source);
SetAttenuation(emitter.GetAttenuation()); SetAttenuation(emitter.GetAttenuation());
SetMinDistance(emitter.GetMinDistance()); SetMinDistance(emitter.GetMinDistance());
SetPitch(emitter.GetPitch()); SetPitch(emitter.GetPitch());
// No copy for position or velocity // No copy for position or velocity
SetVolume(emitter.GetVolume()); SetVolume(emitter.GetVolume());
}
else
m_source = InvalidSource;
}
/*!
* \brief Constructs a SoundEmitter object by moving another
*
* \param emitter SoundEmitter to move
*
* \remark The moved sound emitter cannot be used after being moved
*/
SoundEmitter::SoundEmitter(SoundEmitter&& emitter) noexcept :
m_source(emitter.m_source)
{
emitter.m_source = InvalidSource;
} }
/*! /*!
* \brief Destructs the object * \brief Destructs the object
*/ */
SoundEmitter::~SoundEmitter() SoundEmitter::~SoundEmitter()
{ {
alDeleteSources(1, &m_source); if (m_source != InvalidSource)
alDeleteSources(1, &m_source);
} }
/*! /*!
@ -65,6 +82,8 @@ namespace Nz
void SoundEmitter::EnableSpatialization(bool spatialization) void SoundEmitter::EnableSpatialization(bool spatialization)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcei(m_source, AL_SOURCE_RELATIVE, !spatialization); alSourcei(m_source, AL_SOURCE_RELATIVE, !spatialization);
} }
@ -75,6 +94,8 @@ namespace Nz
float SoundEmitter::GetAttenuation() const float SoundEmitter::GetAttenuation() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALfloat attenuation; ALfloat attenuation;
alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation); alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation);
@ -88,6 +109,8 @@ namespace Nz
float SoundEmitter::GetMinDistance() const float SoundEmitter::GetMinDistance() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALfloat distance; ALfloat distance;
alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance); alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance);
@ -101,6 +124,8 @@ namespace Nz
float SoundEmitter::GetPitch() const float SoundEmitter::GetPitch() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALfloat pitch; ALfloat pitch;
alGetSourcef(m_source, AL_PITCH, &pitch); alGetSourcef(m_source, AL_PITCH, &pitch);
@ -114,6 +139,8 @@ namespace Nz
Vector3f SoundEmitter::GetPosition() const Vector3f SoundEmitter::GetPosition() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
Vector3f position; Vector3f position;
alGetSourcefv(m_source, AL_POSITION, position); alGetSourcefv(m_source, AL_POSITION, position);
@ -127,6 +154,8 @@ namespace Nz
Vector3f SoundEmitter::GetVelocity() const Vector3f SoundEmitter::GetVelocity() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
Vector3f velocity; Vector3f velocity;
alGetSourcefv(m_source, AL_VELOCITY, velocity); alGetSourcefv(m_source, AL_VELOCITY, velocity);
@ -140,6 +169,8 @@ namespace Nz
float SoundEmitter::GetVolume() const float SoundEmitter::GetVolume() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALfloat gain; ALfloat gain;
alGetSourcef(m_source, AL_GAIN, &gain); alGetSourcef(m_source, AL_GAIN, &gain);
@ -153,6 +184,8 @@ namespace Nz
bool SoundEmitter::IsSpatialized() const bool SoundEmitter::IsSpatialized() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALint relative; ALint relative;
alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative); alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative);
@ -167,6 +200,8 @@ namespace Nz
void SoundEmitter::SetAttenuation(float attenuation) void SoundEmitter::SetAttenuation(float attenuation)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation); alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation);
} }
@ -178,6 +213,8 @@ namespace Nz
void SoundEmitter::SetMinDistance(float minDistance) void SoundEmitter::SetMinDistance(float minDistance)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcef(m_source, AL_REFERENCE_DISTANCE, minDistance); alSourcef(m_source, AL_REFERENCE_DISTANCE, minDistance);
} }
@ -189,6 +226,8 @@ namespace Nz
void SoundEmitter::SetPitch(float pitch) void SoundEmitter::SetPitch(float pitch)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcef(m_source, AL_PITCH, pitch); alSourcef(m_source, AL_PITCH, pitch);
} }
@ -200,6 +239,8 @@ namespace Nz
void SoundEmitter::SetPosition(const Vector3f& position) void SoundEmitter::SetPosition(const Vector3f& position)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcefv(m_source, AL_POSITION, position); alSourcefv(m_source, AL_POSITION, position);
} }
@ -211,6 +252,8 @@ namespace Nz
void SoundEmitter::SetPosition(float x, float y, float z) void SoundEmitter::SetPosition(float x, float y, float z)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSource3f(m_source, AL_POSITION, x, y, z); alSource3f(m_source, AL_POSITION, x, y, z);
} }
@ -222,6 +265,8 @@ namespace Nz
void SoundEmitter::SetVelocity(const Vector3f& velocity) void SoundEmitter::SetVelocity(const Vector3f& velocity)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcefv(m_source, AL_VELOCITY, velocity); alSourcefv(m_source, AL_VELOCITY, velocity);
} }
@ -233,6 +278,8 @@ namespace Nz
void SoundEmitter::SetVelocity(float velX, float velY, float velZ) void SoundEmitter::SetVelocity(float velX, float velY, float velZ)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSource3f(m_source, AL_VELOCITY, velX, velY, velZ); alSource3f(m_source, AL_VELOCITY, velX, velY, velZ);
} }
@ -244,9 +291,25 @@ namespace Nz
void SoundEmitter::SetVolume(float volume) void SoundEmitter::SetVolume(float volume)
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
alSourcef(m_source, AL_GAIN, volume * 0.01f); alSourcef(m_source, AL_GAIN, volume * 0.01f);
} }
/*!
* \brief Assign a sound emitter by moving it
*
* \param emitter SoundEmitter to move
*
* \return *this
*/
SoundEmitter& SoundEmitter::operator=(SoundEmitter&& emitter) noexcept
{
std::swap(m_source, emitter.m_source);
return *this;
}
/*! /*!
* \brief Gets the status of the sound emitter * \brief Gets the status of the sound emitter
* \return Enumeration of type SoundStatus (Playing, Stopped, ...) * \return Enumeration of type SoundStatus (Playing, Stopped, ...)
@ -254,6 +317,8 @@ namespace Nz
SoundStatus SoundEmitter::GetInternalStatus() const SoundStatus SoundEmitter::GetInternalStatus() const
{ {
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
ALint state; ALint state;
alGetSourcei(m_source, AL_SOURCE_STATE, &state); alGetSourcei(m_source, AL_SOURCE_STATE, &state);