Audio: Rewrite audio module
This commit is contained in:
298
src/Nazara/Audio/OpenALSource.cpp
Normal file
298
src/Nazara/Audio/OpenALSource.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
// Copyright (C) 2022 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/OpenALSource.hpp>
|
||||
#include <Nazara/Audio/OpenALBuffer.hpp>
|
||||
#include <Nazara/Audio/OpenALLibrary.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StackArray.hpp>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
OpenALSource::~OpenALSource()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alDeleteSources(1, &m_sourceId);
|
||||
}
|
||||
|
||||
void OpenALSource::EnableLooping(bool loop)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
m_library.alSourcei(m_sourceId, AL_LOOPING, loop);
|
||||
}
|
||||
|
||||
void OpenALSource::EnableSpatialization(bool spatialization)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
m_library.alSourcei(m_sourceId, AL_SOURCE_RELATIVE, !spatialization);
|
||||
}
|
||||
|
||||
float OpenALSource::GetAttenuation() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALfloat attenuation;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_ROLLOFF_FACTOR, &attenuation);
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
float OpenALSource::GetMinDistance() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALfloat minDistance;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_REFERENCE_DISTANCE, &minDistance);
|
||||
|
||||
return minDistance;
|
||||
}
|
||||
|
||||
float OpenALSource::GetPitch() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALfloat pitch;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_PITCH, &pitch);
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
Vector3f OpenALSource::GetPosition() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
Vector3f position;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_POSITION, &position.x);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
UInt32 OpenALSource::GetSampleOffset() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint samples = 0;
|
||||
m_library.alGetSourcei(m_sourceId, AL_SAMPLE_OFFSET, &samples);
|
||||
|
||||
return SafeCast<UInt32>(samples);
|
||||
}
|
||||
|
||||
Vector3f OpenALSource::GetVelocity() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
Vector3f velocity;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_VELOCITY, &velocity.x);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
|
||||
SoundStatus OpenALSource::GetStatus() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint state;
|
||||
m_library.alGetSourcei(m_sourceId, 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;
|
||||
}
|
||||
|
||||
float OpenALSource::GetVolume() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALfloat volume;
|
||||
m_library.alGetSourcefv(m_sourceId, AL_GAIN, &volume);
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
bool OpenALSource::IsLooping() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint relative;
|
||||
m_library.alGetSourcei(m_sourceId, AL_LOOPING, &relative);
|
||||
|
||||
return relative == AL_FALSE;
|
||||
}
|
||||
|
||||
bool OpenALSource::IsSpatializationEnabled() const
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint relative;
|
||||
m_library.alGetSourcei(m_sourceId, AL_SOURCE_RELATIVE, &relative);
|
||||
|
||||
return relative == AL_FALSE;
|
||||
}
|
||||
|
||||
void OpenALSource::QueueBuffer(std::shared_ptr<AudioBuffer> audioBuffer)
|
||||
{
|
||||
NazaraAssert(audioBuffer, "invalid buffer");
|
||||
NazaraAssert(audioBuffer->GetAudioDevice() == GetAudioDevice(), "incompatible buffer");
|
||||
|
||||
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
||||
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALuint bufferId = newBuffer->GetBufferId();
|
||||
m_library.alSourceQueueBuffers(m_sourceId, 1, &bufferId);
|
||||
|
||||
m_queuedBuffers.emplace_back(std::move(newBuffer));
|
||||
}
|
||||
|
||||
void OpenALSource::Pause()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcePause(m_sourceId);
|
||||
}
|
||||
|
||||
void OpenALSource::Play()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcePlay(m_sourceId);
|
||||
}
|
||||
|
||||
void OpenALSource::SetAttenuation(float attenuation)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcef(m_sourceId, AL_ROLLOFF_FACTOR, attenuation);
|
||||
}
|
||||
|
||||
void OpenALSource::SetBuffer(std::shared_ptr<AudioBuffer> audioBuffer)
|
||||
{
|
||||
NazaraAssert(audioBuffer->GetAudioDevice() == GetAudioDevice(), "incompatible buffer");
|
||||
|
||||
std::shared_ptr<OpenALBuffer> newBuffer = std::static_pointer_cast<OpenALBuffer>(std::move(audioBuffer));
|
||||
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
if (newBuffer)
|
||||
m_library.alSourcei(m_sourceId, AL_BUFFER, newBuffer->GetBufferId());
|
||||
else
|
||||
m_library.alSourcei(m_sourceId, AL_BUFFER, AL_NONE);
|
||||
|
||||
m_currentBuffer = std::move(newBuffer);
|
||||
}
|
||||
|
||||
void OpenALSource::SetMinDistance(float minDistance)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcef(m_sourceId, AL_REFERENCE_DISTANCE, minDistance);
|
||||
}
|
||||
|
||||
void OpenALSource::SetPitch(float pitch)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcef(m_sourceId, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
void OpenALSource::SetPosition(const Vector3f& position)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSource3f(m_sourceId, AL_POSITION, position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
void OpenALSource::SetSampleOffset(UInt32 offset)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcei(m_sourceId, AL_SAMPLE_OFFSET, offset);
|
||||
}
|
||||
|
||||
void OpenALSource::SetVelocity(const Vector3f& velocity)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSource3f(m_sourceId, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
}
|
||||
|
||||
void OpenALSource::SetVolume(float volume)
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourcef(m_sourceId, AL_GAIN, volume);
|
||||
}
|
||||
|
||||
void OpenALSource::Stop()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
m_library.alSourceStop(m_sourceId);
|
||||
}
|
||||
|
||||
std::shared_ptr<AudioBuffer> OpenALSource::TryUnqueueProcessedBuffer()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint processedCount = 0;
|
||||
m_library.alGetSourcei(m_sourceId, AL_BUFFERS_PROCESSED, &processedCount);
|
||||
|
||||
if (processedCount == 0)
|
||||
return {};
|
||||
|
||||
ALuint bufferId;
|
||||
m_library.alSourceUnqueueBuffers(m_sourceId, 1, &bufferId);
|
||||
|
||||
auto it = std::find_if(m_queuedBuffers.begin(), m_queuedBuffers.end(), [=](const std::shared_ptr<OpenALBuffer>& alBuffer)
|
||||
{
|
||||
return alBuffer->GetBufferId() == bufferId;
|
||||
});
|
||||
assert(it != m_queuedBuffers.end());
|
||||
|
||||
std::shared_ptr<AudioBuffer> buffer = *it;
|
||||
m_queuedBuffers.erase(it);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void OpenALSource::UnqueueAllBuffers()
|
||||
{
|
||||
GetDevice().MakeContextCurrent();
|
||||
|
||||
ALint queuedBufferCount = 0;
|
||||
m_library.alGetSourcei(m_sourceId, AL_BUFFERS_QUEUED, &queuedBufferCount);
|
||||
|
||||
StackArray<ALuint> buffers = NazaraStackArrayNoInit(ALuint, queuedBufferCount);
|
||||
m_library.alSourceUnqueueBuffers(m_sourceId, queuedBufferCount, buffers.data());
|
||||
|
||||
m_queuedBuffers.clear();
|
||||
}
|
||||
|
||||
OpenALDevice& OpenALSource::GetDevice()
|
||||
{
|
||||
return SafeCast<OpenALDevice&>(*GetAudioDevice());
|
||||
}
|
||||
|
||||
const OpenALDevice& OpenALSource::GetDevice() const
|
||||
{
|
||||
return SafeCast<OpenALDevice&>(*GetAudioDevice());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user