Upgrade NazaraAudio

This commit is contained in:
Jérôme Leclercq 2021-05-22 18:20:27 +02:00
parent a52103a641
commit b936946154
13 changed files with 206 additions and 243 deletions

View File

@ -10,6 +10,8 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Audio/SoundBuffer.hpp>
#include <Nazara/Audio/SoundStream.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector3.hpp>
@ -26,18 +28,23 @@ namespace Nz
struct Config {};
Audio(Config /*config*/);
Audio(const Audio&) = delete;
Audio(Audio&&) = delete;
~Audio();
AudioFormat GetAudioFormat(unsigned int channelCount);
float GetDopplerFactor();
float GetGlobalVolume();
Vector3f GetListenerDirection();
Vector3f GetListenerPosition();
Quaternionf GetListenerRotation();
Vector3f GetListenerVelocity();
float GetSpeedOfSound();
AudioFormat GetAudioFormat(unsigned int channelCount) const;
float GetDopplerFactor() const;
float GetGlobalVolume() const;
Vector3f GetListenerDirection() const;
Vector3f GetListenerPosition() const;
Quaternionf GetListenerRotation() const;
Vector3f GetListenerVelocity() const;
const SoundBufferLoader& GetSoundBufferLoader() const;
const SoundStreamLoader& GetSoundStreamLoader() const;
float GetSpeedOfSound() const;
bool IsFormatSupported(AudioFormat format) const;
bool IsFormatSupported(AudioFormat format);
void SetDopplerFactor(float dopplerFactor);
void SetGlobalVolume(float volume);
void SetListenerDirection(const Vector3f& direction);
@ -49,7 +56,13 @@ namespace Nz
void SetListenerVelocity(float velX, float velY, float velZ);
void SetSpeedOfSound(float speed);
Audio& operator=(const Audio&) = delete;
Audio& operator=(Audio&&) = delete;
private:
SoundBufferLoader m_soundBufferLoader;
SoundStreamLoader m_soundStreamLoader;
static Audio* s_instance;
};
}

View File

@ -11,7 +11,6 @@
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Audio/SoundEmitter.hpp>
#include <Nazara/Audio/SoundStream.hpp>
#include <Nazara/Core/MovablePtr.hpp>
namespace Nz
{
@ -20,12 +19,12 @@ namespace Nz
class NAZARA_AUDIO_API Music : public Resource, public SoundEmitter
{
public:
Music() = default;
Music();
Music(const Music&) = delete;
Music(Music&&) noexcept = default;
Music(Music&&) noexcept;
~Music();
bool Create(SoundStream* soundStream);
bool Create(std::shared_ptr<SoundStream> soundStream);
void Destroy();
void EnableLooping(bool loop) override;
@ -51,10 +50,10 @@ namespace Nz
void Stop() override;
Music& operator=(const Music&) = delete;
Music& operator=(Music&&) noexcept = default;
Music& operator=(Music&&) noexcept;
private:
MovablePtr<MusicImpl> m_impl;
std::unique_ptr<MusicImpl> m_impl;
bool FillAndQueueBuffer(unsigned int buffer);
void MusicThread();

View File

@ -18,14 +18,14 @@ namespace Nz
{
public:
Sound() = default;
Sound(const SoundBuffer* soundBuffer);
Sound(const Sound& sound);
Sound(std::shared_ptr<const SoundBuffer> soundBuffer);
Sound(const Sound&) = default;
Sound(Sound&&) noexcept = default;
~Sound();
void EnableLooping(bool loop) override;
const SoundBuffer* GetBuffer() const;
const std::shared_ptr<const SoundBuffer>& GetBuffer() const;
UInt32 GetDuration() const override;
UInt32 GetPlayingOffset() const override;
SoundStatus GetStatus() const override;
@ -41,7 +41,7 @@ namespace Nz
void Pause() override;
void Play() override;
void SetBuffer(const SoundBuffer* buffer);
void SetBuffer(std::shared_ptr<const SoundBuffer> soundBuffer);
void SetPlayingOffset(UInt32 offset);
void Stop() override;
@ -50,7 +50,7 @@ namespace Nz
Sound& operator=(Sound&&) noexcept = default;
private:
SoundBufferConstRef m_buffer;
std::shared_ptr<const SoundBuffer> m_buffer;
};
}

View File

@ -10,7 +10,6 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Core/RefCounted.hpp>
@ -32,24 +31,18 @@ namespace Nz
class Sound;
class SoundBuffer;
using SoundBufferConstRef = ObjectRef<const SoundBuffer>;
using SoundBufferLibrary = ObjectLibrary<SoundBuffer>;
using SoundBufferLoader = ResourceLoader<SoundBuffer, SoundBufferParams>;
using SoundBufferManager = ResourceManager<SoundBuffer, SoundBufferParams>;
using SoundBufferRef = ObjectRef<SoundBuffer>;
struct SoundBufferImpl;
class NAZARA_AUDIO_API SoundBuffer : public RefCounted, public Resource
{
friend Sound;
friend SoundBufferLibrary;
friend SoundBufferLoader;
friend SoundBufferManager;
friend class Audio;
public:
SoundBuffer() = default;
SoundBuffer();
SoundBuffer(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const Int16* samples);
SoundBuffer(const SoundBuffer&) = delete;
SoundBuffer(SoundBuffer&&) = delete;
@ -71,28 +64,14 @@ namespace Nz
static bool IsFormatSupported(AudioFormat format);
static SoundBufferRef LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params = SoundBufferParams());
static SoundBufferRef LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params = SoundBufferParams());
static SoundBufferRef LoadFromStream(Stream& stream, const SoundBufferParams& params = SoundBufferParams());
template<typename... Args> static SoundBufferRef New(Args&&... args);
// Signals:
NazaraSignal(OnSoundBufferDestroy, const SoundBuffer* /*soundBuffer*/);
NazaraSignal(OnSoundBufferRelease, const SoundBuffer* /*soundBuffer*/);
static std::shared_ptr<SoundBuffer> LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params = SoundBufferParams());
static std::shared_ptr<SoundBuffer> LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params = SoundBufferParams());
static std::shared_ptr<SoundBuffer> LoadFromStream(Stream& stream, const SoundBufferParams& params = SoundBufferParams());
private:
unsigned int GetOpenALBuffer() const;
static bool Initialize();
static void Uninitialize();
MovablePtr<SoundBufferImpl> m_impl = nullptr;
static SoundBufferLibrary::LibraryMap s_library;
static SoundBufferLoader::LoaderList s_loaders;
static SoundBufferManager::ManagerMap s_managerMap;
static SoundBufferManager::ManagerParams s_managerParameters;
std::unique_ptr<SoundBufferImpl> m_impl;
};
}

View File

@ -2,26 +2,12 @@
// This file is part of the "Nazara Engine - Audio module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Audio/SoundBuffer.hpp>
#include <memory>
#include <Nazara/Audio/Debug.hpp>
namespace Nz
{
/*!
* \brief Creates a new sound buffer from the arguments
* \return A reference to the newly created sound buffer
*
* \param args Arguments for the sound buffer
*/
template<typename... Args>
SoundBufferRef SoundBuffer::New(Args&&... args)
{
std::unique_ptr<SoundBuffer> object(new SoundBuffer(std::forward<Args>(args)...));
object->SetPersistent(false);
return object.release();
}
}
#include <Nazara/Audio/DebugOff.hpp>

View File

@ -10,7 +10,6 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
@ -29,12 +28,9 @@ namespace Nz
class SoundStream;
using SoundStreamLoader = ResourceLoader<SoundStream, SoundStreamParams>;
using SoundStreamRef = Nz::ObjectRef<SoundStream>;
class NAZARA_AUDIO_API SoundStream : public RefCounted, public Resource
class NAZARA_AUDIO_API SoundStream : public Resource
{
friend SoundStreamLoader;
public:
SoundStream() = default;
virtual ~SoundStream();
@ -49,12 +45,9 @@ namespace Nz
virtual void Seek(UInt64 offset) = 0;
virtual UInt64 Tell() = 0;
static SoundStreamRef OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params = SoundStreamParams());
static SoundStreamRef OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params = SoundStreamParams());
static SoundStreamRef OpenFromStream(Stream& stream, const SoundStreamParams& params = SoundStreamParams());
private:
static SoundStreamLoader::LoaderList s_loaders;
static std::shared_ptr<SoundStream> OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params = SoundStreamParams());
static std::shared_ptr<SoundStream> OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params = SoundStreamParams());
static std::shared_ptr<SoundStream> OpenFromStream(Stream& stream, const SoundStreamParams& params = SoundStreamParams());
};
}

View File

@ -30,22 +30,16 @@ namespace Nz
if (!OpenAL::Initialize())
throw std::runtime_error("failed to initialize OpenAL");
if (!SoundBuffer::Initialize())
throw std::runtime_error("failed to initialize sound buffers");
// Definition of the orientation by default
SetListenerDirection(Vector3f::Forward());
// Loaders
Loaders::Register_sndfile();
m_soundBufferLoader.RegisterLoader(Loaders::GetSoundBufferLoader_sndfile());
m_soundStreamLoader.RegisterLoader(Loaders::GetSoundStreamLoader_sndfile());
}
Audio::~Audio()
{
// Loaders
Loaders::Unregister_sndfile();
SoundBuffer::Uninitialize();
OpenAL::Uninitialize();
}
@ -58,7 +52,7 @@ namespace Nz
* \remark Produces a NazaraError if the number of channels is erroneous (3 or 5) and AudioFormat_Unknown is returned
*/
AudioFormat Audio::GetAudioFormat(unsigned int channelCount)
AudioFormat Audio::GetAudioFormat(unsigned int channelCount) const
{
switch (channelCount)
{
@ -80,8 +74,7 @@ namespace Nz
* \brief Gets the factor of the doppler effect
* \return Global factor of the doppler effect
*/
float Audio::GetDopplerFactor()
float Audio::GetDopplerFactor() const
{
return alGetFloat(AL_DOPPLER_FACTOR);
}
@ -90,8 +83,7 @@ namespace Nz
* \brief Gets the global volume
* \return Float between [0, inf) with 100.f being the default
*/
float Audio::GetGlobalVolume()
float Audio::GetGlobalVolume() const
{
ALfloat gain = 0.f;
alGetListenerf(AL_GAIN, &gain);
@ -105,8 +97,7 @@ namespace Nz
*
* \see GetListenerRotation
*/
Vector3f Audio::GetListenerDirection()
Vector3f Audio::GetListenerDirection() const
{
ALfloat orientation[6];
alGetListenerfv(AL_ORIENTATION, orientation);
@ -120,8 +111,7 @@ namespace Nz
*
* \see GetListenerVelocity
*/
Vector3f Audio::GetListenerPosition()
Vector3f Audio::GetListenerPosition() const
{
Vector3f position;
alGetListenerfv(AL_POSITION, &position.x);
@ -133,8 +123,7 @@ namespace Nz
* \brief Gets the rotation of the listener
* \return Rotation of the listener
*/
Quaternionf Audio::GetListenerRotation()
Quaternionf Audio::GetListenerRotation() const
{
ALfloat orientation[6];
alGetListenerfv(AL_ORIENTATION, orientation);
@ -150,8 +139,7 @@ namespace Nz
*
* \see GetListenerPosition
*/
Vector3f Audio::GetListenerVelocity()
Vector3f Audio::GetListenerVelocity() const
{
Vector3f velocity;
alGetListenerfv(AL_VELOCITY, &velocity.x);
@ -159,12 +147,29 @@ namespace Nz
return velocity;
}
/*!
* \brief Gets the default SoundBuffer loader
* \return A constant reference to the default SoundBuffer loader
*/
const SoundBufferLoader& Audio::GetSoundBufferLoader() const
{
return m_soundBufferLoader;
}
/*!
* \brief Gets the default SoundStream loader
* \return A constant reference to the default SoundStream loader
*/
const SoundStreamLoader& Audio::GetSoundStreamLoader() const
{
return m_soundStreamLoader;
}
/*!
* \brief Gets the speed of sound
* \return Speed of sound
*/
float Audio::GetSpeedOfSound()
float Audio::GetSpeedOfSound() const
{
return alGetFloat(AL_SPEED_OF_SOUND);
}
@ -175,8 +180,7 @@ namespace Nz
*
* \param format Format to check
*/
bool Audio::IsFormatSupported(AudioFormat format)
bool Audio::IsFormatSupported(AudioFormat format) const
{
if (format == AudioFormat_Unknown)
return false;

View File

@ -17,6 +17,7 @@
#include <Nazara/Core/Stream.hpp>
#include <memory>
#include <set>
#include <string_view>
#include <vector>
#include <sndfile.h>
#include <Nazara/Audio/Debug.hpp>
@ -223,9 +224,9 @@ namespace Nz
UInt64 m_sampleCount;
};
bool IsSupported(const std::string& extension)
bool IsSupported(const std::string_view& extension)
{
static std::set<std::string> supportedExtensions = {
static std::set<std::string_view> supportedExtensions = {
"aiff", "au", "avr", "caf", "flac", "htk", "ircam", "mat4", "mat5", "mpc2k",
"nist","ogg", "pvf", "raw", "rf64", "sd2", "sds", "svx", "voc", "w64", "wav", "wve"
};
@ -251,43 +252,40 @@ namespace Nz
return Ternary::False;
}
SoundStreamRef LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters)
std::shared_ptr<SoundStream> LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters)
{
std::unique_ptr<sndfileStream> soundStream = std::make_unique<sndfileStream>();
std::shared_ptr<sndfileStream> soundStream = std::make_shared<sndfileStream>();
if (!soundStream->Open(filePath, parameters.forceMono))
{
NazaraError("Failed to open sound stream");
return nullptr;
return {};
}
soundStream->SetPersistent(false);
return soundStream.release();
return soundStream;
}
SoundStreamRef LoadSoundStreamMemory(const void* data, std::size_t size, const SoundStreamParams& parameters)
std::shared_ptr<SoundStream> LoadSoundStreamMemory(const void* data, std::size_t size, const SoundStreamParams& parameters)
{
std::unique_ptr<sndfileStream> soundStream(new sndfileStream);
std::shared_ptr<sndfileStream> soundStream = std::make_shared<sndfileStream>();
if (!soundStream->Open(data, size, parameters.forceMono))
{
NazaraError("Failed to open music stream");
return nullptr;
return {};
}
soundStream->SetPersistent(false);
return soundStream.release();
return soundStream;
}
SoundStreamRef LoadSoundStreamStream(Stream& stream, const SoundStreamParams& parameters)
std::shared_ptr<SoundStream> LoadSoundStreamStream(Stream& stream, const SoundStreamParams& parameters)
{
std::unique_ptr<sndfileStream> soundStream(new sndfileStream);
if (!soundStream->Open(stream, parameters.forceMono))
{
NazaraError("Failed to open music stream");
return nullptr;
return {};
}
soundStream->SetPersistent(false);
return soundStream.release();
return soundStream;
}
Ternary CheckSoundBuffer(Stream& stream, const SoundBufferParams& parameters)
@ -307,7 +305,7 @@ namespace Nz
return Ternary::False;
}
SoundBufferRef LoadSoundBuffer(Stream& stream, const SoundBufferParams& parameters)
std::shared_ptr<SoundBuffer> LoadSoundBuffer(Stream& stream, const SoundBufferParams& parameters)
{
SF_INFO info;
info.format = 0;
@ -318,10 +316,7 @@ namespace Nz
NazaraError("Failed to load sound file: " + std::string(sf_strerror(file)));
return nullptr;
}
// Lynix utilise RAII...
// C'est très efficace !
// MemoryLeak est confus...
CallOnExit onExit([file]
{
sf_close(file);
@ -336,12 +331,12 @@ namespace Nz
// https://github.com/LaurentGomila/SFML/issues/271
// http://www.mega-nerd.com/libsndfile/command.html#SFC_SET_SCALE_FLOAT_INT_READ
///FIXME: Seulement le Vorbis ?
///FIXME: Only Vorbis?
if (info.format & SF_FORMAT_VORBIS)
sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);
unsigned int sampleCount = static_cast<unsigned int>(info.frames * info.channels);
std::unique_ptr<Int16[]> samples(new Int16[sampleCount]);
sf_count_t sampleCount = static_cast<sf_count_t>(info.frames * info.channels);
std::unique_ptr<Int16[]> samples = std::make_unique<Int16[]>(sampleCount); //< std::vector would default-init to zero
if (sf_read_short(file, samples.get(), sampleCount) != sampleCount)
{
@ -349,32 +344,41 @@ namespace Nz
return nullptr;
}
// Une conversion en mono est-elle nécessaire ?
// Convert to mono if required
if (parameters.forceMono && format != AudioFormat_Mono)
{
// Nous effectuons la conversion en mono dans le même buffer (il va de toute façon être copié)
MixToMono(samples.get(), samples.get(), static_cast<unsigned int>(info.channels), static_cast<unsigned int>(info.frames));
MixToMono(samples.get(), samples.get(), static_cast<UInt32>(info.channels), static_cast<UInt64>(info.frames));
format = AudioFormat_Mono;
sampleCount = static_cast<unsigned int>(info.frames);
}
return SoundBuffer::New(format, sampleCount, info.samplerate, samples.get());
return std::make_shared<SoundBuffer>(format, sampleCount, info.samplerate, samples.get());
}
}
namespace Loaders
{
void Register_sndfile()
SoundBufferLoader::Entry GetSoundBufferLoader_sndfile()
{
SoundBufferLoader::RegisterLoader(Detail::IsSupported, Detail::CheckSoundBuffer, Detail::LoadSoundBuffer);
SoundStreamLoader::RegisterLoader(Detail::IsSupported, Detail::CheckSoundStream, Detail::LoadSoundStreamStream, Detail::LoadSoundStreamFile, Detail::LoadSoundStreamMemory);
SoundBufferLoader::Entry loaderEntry;
loaderEntry.extensionSupport = Detail::IsSupported;
loaderEntry.streamChecker = Detail::CheckSoundBuffer;
loaderEntry.streamLoader = Detail::LoadSoundBuffer;
return loaderEntry;
}
void Unregister_sndfile()
SoundStreamLoader::Entry GetSoundStreamLoader_sndfile()
{
SoundBufferLoader::UnregisterLoader(Detail::IsSupported, Detail::CheckSoundBuffer, Detail::LoadSoundBuffer);
SoundStreamLoader::UnregisterLoader(Detail::IsSupported, Detail::CheckSoundStream, Detail::LoadSoundStreamStream, Detail::LoadSoundStreamFile, Detail::LoadSoundStreamMemory);
SoundStreamLoader::Entry loaderEntry;
loaderEntry.extensionSupport = Detail::IsSupported;
loaderEntry.streamChecker = Detail::CheckSoundStream;
loaderEntry.fileLoader = Detail::LoadSoundStreamFile;
loaderEntry.memoryLoader = Detail::LoadSoundStreamMemory;
loaderEntry.streamLoader = Detail::LoadSoundStreamStream;
return loaderEntry;
}
}
}

View File

@ -8,14 +8,13 @@
#define NAZARA_LOADERS_SNDFILE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/SoundBuffer.hpp>
#include <Nazara/Audio/SoundStream.hpp>
namespace Nz
namespace Nz::Loaders
{
namespace Loaders
{
void Register_sndfile();
void Unregister_sndfile();
}
SoundBufferLoader::Entry GetSoundBufferLoader_sndfile();
SoundStreamLoader::Entry GetSoundStreamLoader_sndfile();
}
#endif // NAZARA_LOADERS_SNDFILE_HPP

View File

@ -29,7 +29,7 @@ namespace Nz
std::atomic<UInt64> processedSamples;
std::vector<Int16> chunkSamples;
std::mutex bufferLock;
SoundStreamRef stream;
std::shared_ptr<SoundStream> stream;
std::thread thread;
UInt64 playingOffset;
bool loop = false;
@ -37,12 +37,14 @@ namespace Nz
unsigned int sampleRate;
};
Music::Music() = default;
Music::Music(Music&&) noexcept = default;
/*!
* \brief Destructs the object and calls Destroy
*
* \see Destroy
*/
Music::~Music()
{
Destroy();
@ -55,7 +57,7 @@ namespace Nz
* \param soundStream Sound stream which is the source for the music
*/
bool Music::Create(SoundStream* soundStream)
bool Music::Create(std::shared_ptr<SoundStream> soundStream)
{
NazaraAssert(soundStream, "Invalid stream");
@ -63,11 +65,11 @@ namespace Nz
AudioFormat format = soundStream->GetFormat();
m_impl = new MusicImpl;
m_impl = std::make_unique<MusicImpl>();
m_impl->sampleRate = soundStream->GetSampleRate();
m_impl->audioFormat = OpenAL::AudioFormat[format];
m_impl->chunkSamples.resize(format * m_impl->sampleRate); // One second of samples
m_impl->stream = soundStream;
m_impl->stream = std::move(soundStream);
SetPlayingOffset(0);
@ -85,8 +87,7 @@ namespace Nz
{
StopThread();
delete m_impl;
m_impl = nullptr;
m_impl.reset();
}
}
@ -216,8 +217,8 @@ namespace Nz
*/
bool Music::OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params)
{
if (SoundStreamRef soundStream = SoundStream::OpenFromFile(filePath, params))
return Create(soundStream);
if (std::shared_ptr<SoundStream> soundStream = SoundStream::OpenFromFile(filePath, params))
return Create(std::move(soundStream));
else
return false;
}
@ -234,8 +235,8 @@ namespace Nz
*/
bool Music::OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params)
{
if (SoundStreamRef soundStream = SoundStream::OpenFromMemory(data, size, params))
return Create(soundStream);
if (std::shared_ptr<SoundStream> soundStream = SoundStream::OpenFromMemory(data, size, params))
return Create(std::move(soundStream));
else
return false;
}
@ -251,8 +252,8 @@ namespace Nz
*/
bool Music::OpenFromStream(Stream& stream, const SoundStreamParams& params)
{
if (SoundStreamRef soundStream = SoundStream::OpenFromStream(stream, params))
return Create(soundStream);
if (std::shared_ptr<SoundStream> soundStream = SoundStream::OpenFromStream(stream, params))
return Create(std::move(soundStream));
else
return false;
}
@ -346,6 +347,8 @@ namespace Nz
SetPlayingOffset(0);
}
Music& Music::operator=(Music&&) noexcept = default;
bool Music::FillAndQueueBuffer(unsigned int buffer)
{
std::size_t sampleCount = m_impl->chunkSamples.size();

View File

@ -23,21 +23,9 @@ namespace Nz
*
* \param soundBuffer Buffer to read sound from
*/
Sound::Sound(const SoundBuffer* soundBuffer)
Sound::Sound(std::shared_ptr<const SoundBuffer> soundBuffer)
{
SetBuffer(soundBuffer);
}
/*!
* \brief Constructs a Sound object which is a copy of another
*
* \param sound Sound to copy
*/
Sound::Sound(const Sound& sound) :
SoundEmitter(sound)
{
SetBuffer(sound.m_buffer);
EnableLooping(sound.IsLooping());
SetBuffer(std::move(soundBuffer));
}
/*!
@ -66,7 +54,7 @@ namespace Nz
* \brief Gets the internal buffer
* \return Internal buffer
*/
const SoundBuffer* Sound::GetBuffer() const
const std::shared_ptr<const SoundBuffer>& Sound::GetBuffer() const
{
return m_buffer;
}
@ -151,7 +139,7 @@ namespace Nz
*/
bool Sound::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
{
SoundBufferRef buffer = SoundBuffer::LoadFromFile(filePath, params);
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromFile(filePath, params);
if (!buffer)
{
NazaraError("Failed to load buffer from file (" + filePath.generic_u8string() + ')');
@ -174,7 +162,7 @@ namespace Nz
*/
bool Sound::LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params)
{
SoundBufferRef buffer = SoundBuffer::LoadFromMemory(data, size, params);
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromMemory(data, size, params);
if (!buffer)
{
NazaraError("Failed to load buffer from memory (" + PointerToString(data) + ')');
@ -196,7 +184,7 @@ namespace Nz
*/
bool Sound::LoadFromStream(Stream& stream, const SoundBufferParams& params)
{
SoundBufferRef buffer = SoundBuffer::LoadFromStream(stream, params);
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromStream(stream, params);
if (!buffer)
{
NazaraError("Failed to load buffer from stream");
@ -237,7 +225,7 @@ namespace Nz
*
* \remark Produces a NazaraError if buffer is invalid with NAZARA_AUDIO_SAFE defined
*/
void Sound::SetBuffer(const SoundBuffer* buffer)
void Sound::SetBuffer(std::shared_ptr<const SoundBuffer> buffer)
{
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
NazaraAssert(!buffer || buffer->IsValid(), "Invalid sound buffer");
@ -247,7 +235,7 @@ namespace Nz
Stop();
m_buffer = buffer;
m_buffer = std::move(buffer);
if (m_buffer)
alSourcei(m_source, AL_BUFFER, m_buffer->GetOpenALBuffer());

View File

@ -45,6 +45,8 @@ namespace Nz
UInt32 sampleRate;
};
SoundBuffer::SoundBuffer() = default;
/*!
* \brief Constructs a SoundBuffer object
*
@ -71,17 +73,7 @@ namespace Nz
#endif
}
/*!
* \brief Destructs the object and calls Destroy
*
* \see Destroy
*/
SoundBuffer::~SoundBuffer()
{
OnSoundBufferRelease(this);
Destroy();
}
SoundBuffer::~SoundBuffer() = default;
/*!
* \brief Creates the SoundBuffer object
@ -146,7 +138,7 @@ namespace Nz
return false;
}
m_impl = new SoundBufferImpl;
m_impl = std::make_unique<SoundBufferImpl>();
m_impl->buffer = buffer;
m_impl->duration = static_cast<UInt32>((1000ULL*sampleCount / (format * sampleRate)));
m_impl->format = format;
@ -163,16 +155,9 @@ namespace Nz
/*!
* \brief Destroys the current sound buffer and frees resources
*/
void SoundBuffer::Destroy()
{
if (m_impl)
{
OnSoundBufferDestroy(this);
delete m_impl;
m_impl = nullptr;
}
m_impl.reset();
}
/*!
@ -259,7 +244,10 @@ namespace Nz
*/
bool SoundBuffer::IsFormatSupported(AudioFormat format)
{
return Audio::Instance()->IsFormatSupported(format);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->IsFormatSupported(format);
}
/*!
@ -269,9 +257,12 @@ namespace Nz
* \param filePath Path to the file
* \param params Parameters for the sound buffer
*/
SoundBufferRef SoundBuffer::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
std::shared_ptr<SoundBuffer> SoundBuffer::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
{
return SoundBufferLoader::LoadFromFile(filePath, params);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->GetSoundBufferLoader().LoadFromFile(filePath, params);
}
/*!
@ -282,9 +273,12 @@ namespace Nz
* \param size Size of the memory
* \param params Parameters for the sound buffer
*/
SoundBufferRef SoundBuffer::LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params)
std::shared_ptr<SoundBuffer> SoundBuffer::LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params)
{
return SoundBufferLoader::LoadFromMemory(data, size, params);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->GetSoundBufferLoader().LoadFromMemory(data, size, params);
}
/*!
@ -294,9 +288,12 @@ namespace Nz
* \param stream Stream to the sound buffer
* \param params Parameters for the sound buffer
*/
SoundBufferRef SoundBuffer::LoadFromStream(Stream& stream, const SoundBufferParams& params)
std::shared_ptr<SoundBuffer> SoundBuffer::LoadFromStream(Stream& stream, const SoundBufferParams& params)
{
return SoundBufferLoader::LoadFromStream(stream, params);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->GetSoundBufferLoader().LoadFromStream(stream, params);
}
/*!
@ -317,41 +314,4 @@ namespace Nz
return m_impl->buffer;
}
/*!
* \brief Initializes the libraries and managers
* \return true if initialization is successful
*
* \remark Produces a NazaraError if sub-initialization failed
*/
bool SoundBuffer::Initialize()
{
if (!SoundBufferLibrary::Initialize())
{
NazaraError("Failed to initialise library");
return false;
}
if (!SoundBufferManager::Initialize())
{
NazaraError("Failed to initialise manager");
return false;
}
return true;
}
/*!
* \brief Uninitializes the libraries and managers
*/
void SoundBuffer::Uninitialize()
{
SoundBufferManager::Uninitialize();
SoundBufferLibrary::Uninitialize();
}
SoundBufferLibrary::LibraryMap SoundBuffer::s_library;
SoundBufferLoader::LoaderList SoundBuffer::s_loaders;
SoundBufferManager::ManagerMap SoundBuffer::s_managerMap;
SoundBufferManager::ManagerParams SoundBuffer::s_managerParameters;
}

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Audio/SoundStream.hpp>
#include <Nazara/Audio/Audio.hpp>
namespace Nz
{
@ -18,23 +19,57 @@ namespace Nz
*
* \remark This class is abstract
*/
SoundStream::~SoundStream() = default;
SoundStreamRef SoundStream::OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params)
/*!
* \brief Opens the sound stream from file
* \return true if loading is successful
*
* \param filePath Path to the file
* \param params Parameters for the sound stream
*
* \remark The file must stay valid until the sound stream is destroyed
*/
std::shared_ptr<SoundStream> SoundStream::OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params)
{
return SoundStreamLoader::LoadFromFile(filePath, params);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->GetSoundStreamLoader().LoadFromFile(filePath, params);
}
SoundStreamRef SoundStream::OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params)
/*!
* \brief Opens the sound stream from memory
* \return true if loading is successful
*
* \param data Raw memory
* \param size Size of the memory
* \param params Parameters for the sound stream
*
* \remark The memory block must stay valid until the sound stream is destroyed
*/
std::shared_ptr<SoundStream> SoundStream::OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params)
{
return SoundStreamLoader::LoadFromMemory(data, size, params);
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
return audio->GetSoundStreamLoader().LoadFromMemory(data, size, params);
}
SoundStreamRef SoundStream::OpenFromStream(Stream& stream, const SoundStreamParams& params)
/*!
* \brief Opens the sound stream from stream
* \return true if loading is successful
*
* \param stream Stream to the sound stream
* \param params Parameters for the sound stream
*
* \remark The stream must stay valid until the sound stream is destroyed
*/
std::shared_ptr<SoundStream> SoundStream::OpenFromStream(Stream& stream, const SoundStreamParams& params)
{
return SoundStreamLoader::LoadFromStream(stream, params);
}
Audio* audio = Audio::Instance();
NazaraAssert(audio, "Audio module has not been initialized");
SoundStreamLoader::LoaderList SoundStream::s_loaders;
return audio->GetSoundStreamLoader().LoadFromStream(stream, params);
}
}