344 lines
7.2 KiB
C++
344 lines
7.2 KiB
C++
// Copyright (C) 2020 Jérôme Leclercq
|
|
// This file is part of the "Nazara Engine - Audio module"
|
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
|
|
// http://connect.creativelabs.com/openal/Documentation/OpenAL_Programmers_Guide.pdf
|
|
|
|
#include <Nazara/Audio/SoundEmitter.hpp>
|
|
#include <Nazara/Audio/OpenAL.hpp>
|
|
#include <Nazara/Core/Error.hpp>
|
|
#include <Nazara/Audio/Debug.hpp>
|
|
|
|
namespace Nz
|
|
{
|
|
/*!
|
|
* \ingroup audio
|
|
* \class Nz::SoundEmitter
|
|
* \brief Audio class that represents a sound source, that emits sound
|
|
*
|
|
* \remark Module Audio needs to be initialized to use this class
|
|
* \remark This class is abstract
|
|
*/
|
|
|
|
/*!
|
|
* \brief Constructs a SoundEmitter object
|
|
*/
|
|
SoundEmitter::SoundEmitter()
|
|
{
|
|
alGenSources(1, &m_source);
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a SoundEmitter object which is a copy of another
|
|
*
|
|
* \param emitter SoundEmitter to copy
|
|
*
|
|
* \remark Position and velocity are not copied
|
|
*/
|
|
|
|
SoundEmitter::SoundEmitter(const SoundEmitter& emitter)
|
|
{
|
|
if (emitter.m_source != InvalidSource)
|
|
{
|
|
alGenSources(1, &m_source);
|
|
|
|
SetAttenuation(emitter.GetAttenuation());
|
|
SetMinDistance(emitter.GetMinDistance());
|
|
SetPitch(emitter.GetPitch());
|
|
// No copy for position or velocity
|
|
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
|
|
*/
|
|
SoundEmitter::~SoundEmitter()
|
|
{
|
|
if (m_source != InvalidSource)
|
|
alDeleteSources(1, &m_source);
|
|
}
|
|
|
|
/*!
|
|
* \brief Enables spatialization
|
|
*
|
|
* \param spatialization True if spatialization is enabled
|
|
*/
|
|
|
|
void SoundEmitter::EnableSpatialization(bool spatialization)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcei(m_source, AL_SOURCE_RELATIVE, !spatialization);
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the attenuation
|
|
* \return Amount that your sound will drop off as by the inverse square law
|
|
*/
|
|
|
|
float SoundEmitter::GetAttenuation() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALfloat attenuation;
|
|
alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation);
|
|
|
|
return attenuation;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the minimum distance to hear
|
|
* \return Distance to begin to hear
|
|
*/
|
|
|
|
float SoundEmitter::GetMinDistance() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALfloat distance;
|
|
alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance);
|
|
|
|
return distance;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the pitch
|
|
* \return Pitch of the sound
|
|
*/
|
|
|
|
float SoundEmitter::GetPitch() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALfloat pitch;
|
|
alGetSourcef(m_source, AL_PITCH, &pitch);
|
|
|
|
return pitch;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the position of the emitter
|
|
* \return Position of the sound
|
|
*/
|
|
|
|
Vector3f SoundEmitter::GetPosition() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
Vector3f position;
|
|
alGetSourcefv(m_source, AL_POSITION, &position.x);
|
|
|
|
return position;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the velocity of the emitter
|
|
* \return Velocity of the sound
|
|
*/
|
|
|
|
Vector3f SoundEmitter::GetVelocity() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
Vector3f velocity;
|
|
alGetSourcefv(m_source, AL_VELOCITY, &velocity.x);
|
|
|
|
return velocity;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the volume of the emitter
|
|
* \param volume Float between [0, inf) with 100.f being the default
|
|
*/
|
|
|
|
float SoundEmitter::GetVolume() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALfloat gain;
|
|
alGetSourcef(m_source, AL_GAIN, &gain);
|
|
|
|
return gain * 100.f;
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the sound emitter has spatialization enabled
|
|
* \return true if it the case
|
|
*/
|
|
|
|
bool SoundEmitter::IsSpatialized() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALint relative;
|
|
alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative);
|
|
|
|
return relative == AL_FALSE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the attenuation
|
|
*
|
|
* \param attenuation Amount that your sound will drop off as by the inverse square law
|
|
*/
|
|
|
|
void SoundEmitter::SetAttenuation(float attenuation)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the minimum distance to hear
|
|
*
|
|
* \param minDistance to begin to hear
|
|
*/
|
|
|
|
void SoundEmitter::SetMinDistance(float minDistance)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcef(m_source, AL_REFERENCE_DISTANCE, minDistance);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the pitch
|
|
*
|
|
* \param pitch of the sound
|
|
*/
|
|
|
|
void SoundEmitter::SetPitch(float pitch)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcef(m_source, AL_PITCH, pitch);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the position of the emitter
|
|
*
|
|
* \param position Position of the sound
|
|
*/
|
|
|
|
void SoundEmitter::SetPosition(const Vector3f& position)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcefv(m_source, AL_POSITION, &position.x);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the position of the emitter
|
|
*
|
|
* \param position Position of the sound with (x, y, 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);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the velocity of the emitter
|
|
*
|
|
* \param velocity Velocity of the sound
|
|
*/
|
|
|
|
void SoundEmitter::SetVelocity(const Vector3f& velocity)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
alSourcefv(m_source, AL_VELOCITY, &velocity.x);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the velocity of the emitter
|
|
*
|
|
* \param velocity Velocity with (velX, velY, 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);
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the volume of the emitter
|
|
*
|
|
* \param volume Float between [0, inf) with 100.f being the default
|
|
*/
|
|
|
|
void SoundEmitter::SetVolume(float volume)
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
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
|
|
* \return Enumeration of type SoundStatus (Playing, Stopped, ...)
|
|
*/
|
|
|
|
SoundStatus SoundEmitter::GetInternalStatus() const
|
|
{
|
|
NazaraAssert(m_source != InvalidSource, "Invalid sound emitter");
|
|
|
|
ALint state;
|
|
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
|
|
|
|
switch (state)
|
|
{
|
|
case AL_INITIAL:
|
|
case AL_STOPPED:
|
|
return SoundStatus_Stopped;
|
|
|
|
case AL_PAUSED:
|
|
return SoundStatus_Paused;
|
|
|
|
case AL_PLAYING:
|
|
return SoundStatus_Playing;
|
|
|
|
default:
|
|
NazaraInternalError("Source state unrecognized");
|
|
}
|
|
|
|
return SoundStatus_Stopped;
|
|
}
|
|
}
|