Files
NazaraEngine/src/Nazara/Audio/Sound.cpp
2023-01-22 17:41:18 +01:00

257 lines
5.1 KiB
C++

// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// 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/Sound.hpp>
#include <Nazara/Audio/Audio.hpp>
#include <Nazara/Audio/AudioSource.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Audio/Debug.hpp>
namespace Nz
{
/*!
* \ingroup audio
* \class Nz::Sound
* \brief Audio class that represents a sound
*
* \remark Module Audio needs to be initialized to use this class
*/
Sound::Sound() :
Sound(*Audio::Instance()->GetDefaultDevice())
{
}
/*!
* \brief Constructs a Sound object
*
* \param soundBuffer Buffer to read sound from
*/
Sound::Sound(AudioDevice& audioDevice, std::shared_ptr<SoundBuffer> soundBuffer) :
Sound(audioDevice)
{
SetBuffer(std::move(soundBuffer));
}
/*!
* \brief Destructs the object and calls Stop
*
* \see Stop
*/
Sound::~Sound()
{
if (m_source)
Stop();
}
/*!
* \brief Enables the looping of the music
*
* \param loop Should sound loop
*/
void Sound::EnableLooping(bool loop)
{
m_source->EnableLooping(loop);
}
/*!
* \brief Gets the internal buffer
* \return Internal buffer
*/
const std::shared_ptr<SoundBuffer>& Sound::GetBuffer() const
{
return m_buffer;
}
/*!
* \brief Gets the duration of the sound
* \return Duration of the music in milliseconds
*
* \remark Produces a NazaraError if there is no buffer
*/
Time Sound::GetDuration() const
{
NazaraAssert(m_buffer, "Invalid sound buffer");
return m_buffer->GetDuration();
}
/*!
* \brief Gets the current playing offset of the sound
* \return Offset
*/
Time Sound::GetPlayingOffset() const
{
return m_source->GetPlayingOffset();
}
/*!
* \brief Gets the current sample offset of the sound
* \return Offset
*/
UInt64 Sound::GetSampleOffset() const
{
return m_source->GetSampleOffset();
}
/*!
* \brief Gets the sample rate of the sound
* \return Offset
*/
UInt32 Sound::GetSampleRate() const
{
return m_buffer->GetSampleRate();
}
/*!
* \brief Gets the status of the music
* \return Enumeration of type SoundStatus (Playing, Stopped, ...)
*/
SoundStatus Sound::GetStatus() const
{
return m_source->GetStatus();
}
/*!
* \brief Checks whether the sound is looping
* \return true if it is the case
*/
bool Sound::IsLooping() const
{
return m_source->IsLooping();
}
/*!
* \brief Checks whether the sound is playable
* \return true if it is the case
*/
bool Sound::IsPlayable() const
{
return m_buffer != nullptr;
}
/*!
* \brief Loads the sound from file
* \return true if loading is successful
*
* \param filePath Path to the file
* \param params Parameters for the sound
*
* \remark Produces a NazaraError if loading failed
*/
bool Sound::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
{
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromFile(filePath, params);
if (!buffer)
{
NazaraError("Failed to load buffer from file (" + filePath.generic_u8string() + ')');
return false;
}
SetBuffer(std::move(buffer));
return true;
}
/*!
* \brief Loads the sound from memory
* \return true if loading is successful
*
* \param data Raw memory
* \param size Size of the memory
* \param params Parameters for the sound
*
* \remark Produces a NazaraError if loading failed
*/
bool Sound::LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params)
{
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromMemory(data, size, params);
if (!buffer)
{
NazaraError("Failed to load buffer from memory (" + PointerToString(data) + ')');
return false;
}
SetBuffer(std::move(buffer));
return true;
}
/*!
* \brief Loads the sound from stream
* \return true if loading is successful
*
* \param stream Stream to the sound
* \param params Parameters for the sound
*
* \remark Produces a NazaraError if loading failed
*/
bool Sound::LoadFromStream(Stream& stream, const SoundBufferParams& params)
{
std::shared_ptr<SoundBuffer> buffer = SoundBuffer::LoadFromStream(stream, params);
if (!buffer)
{
NazaraError("Failed to load buffer from stream");
return false;
}
SetBuffer(std::move(buffer));
return true;
}
/*!
* \brief Pauses the sound
*/
void Sound::Pause()
{
m_source->Pause();
}
/*!
* \brief Plays the music
*/
void Sound::Play()
{
NazaraAssert(IsPlayable(), "Sound is not playable");
m_source->Play();
}
/*!
* \brief Sets the audio buffer
*
* \param buffer Audio buffer
*/
void Sound::SetBuffer(std::shared_ptr<SoundBuffer> buffer)
{
NazaraAssert(buffer, "Invalid sound buffer");
if (m_buffer == buffer)
return;
Stop();
m_buffer = std::move(buffer);
m_source->SetBuffer(m_buffer->GetAudioBuffer(m_source->GetAudioDevice().get()));
}
/*!
* \brief Sets the source to a sample offset
*
* \param offset Sample offset
*/
void Sound::SeekToSampleOffset(UInt64 offset)
{
m_source->SetSampleOffset(SafeCast<UInt32>(offset));
}
/*!
* \brief Stops the sound
*/
void Sound::Stop()
{
m_source->Stop();
}
}