OpenAL Seperation and Adjustments (#34)

* OpenAL adjustments and improvements mk.1

Seperated SoundSystemAl from the sdl section and into platform/openal.
Made PlatformDefinitions.hpp require a "USE_OPENAL" definition instead of "USE_SDL" definition for OpenAL
Added SoundSystemAl.cpp  and SoundSystemAL.hpp files to the actual solution file so it can be compiled properly.
Made the SoundSystemAl use headers from thirdparty/OpenAL/include folder.
Made the SoundSystemAl use #pragma comment(lib, "OpenAL32.lib") to include the library if needed without adding it to the linker input value in the solution file.
Added thirdparty/OpenAL/libs/Win64/thirdparty/OpenAL/libs/Win32 to the additional libraries so that it can find the OpenAL32.lib library.

* OpenAL adjustments and improvements mk.2

Removed specific USE_SDL preprocessor definitions related to OpenAL which were unhelpful/unneeded for multi-platform use.
Made the OpenAl sound system inherit from the SoundSystem class and implement the functions properly without requiring a custom update function.
Fixed an error that would happen when closing the game related to OpenAl closing the sound device.
Removed unnecessary is_ui check in OpenAL sound system, UI sounds work just fine without it.
Adjusted rolloff factor, not sure if this is just placebo but it felt a bit better?

* Update sdl/CMakeLists.txt for new OpenAL stuff

* CMakeLists name fix

* Minor fixes for SDL compatibility

* Added check for absolute zero position

Made the OpenAL sound system consider any sound that is at absolute zero non-spatial

Also removed unneeded ORIGINAL_CODE check in SoundSystem.hpp and SoundSystem.cpp

* Fixed OpenAL popping strangeness

OpenAL apparently makes weird popping noises when the gain of a sound is below 0, so I added a check to see if the distance is too far (for the new updated settings)

I did some graphing and the previous settings for OpenAL were limiting the sound distance to 8 blocks (which was causing popping when sounds were between 8-16 blocks away as the gain was 0 or below) so I changed the rolloff factor to 1.0f to make sounds falloff at 16 blocks instead which seems reasonable/like the original intention.

* Minor Fix to solution additional includes

* Forgot an sdl compat change
This commit is contained in:
Vruk
2023-08-08 01:12:08 -07:00
committed by GitHub
parent c0ef625972
commit 3447669f04
11 changed files with 160 additions and 132 deletions

View File

@@ -0,0 +1,323 @@
#include "SoundSystemAL.hpp"
#include "client/common/Utils.hpp"
SoundSystemAL::SoundSystemAL()
{
device = alcOpenDevice(NULL);
if (!device)
{
LogMsg("Unable To Load Audio Engine");
return;
}
// Create Context
context = alcCreateContext(device, NULL);
ALCenum err = alcGetError(device);
if (err != ALC_NO_ERROR)
{
LogMsg("Unable To Open Audio Context: %s", alcGetString(device, err));
return;
}
// Select Context
alcMakeContextCurrent(context);
err = alcGetError(device);
if (err != ALC_NO_ERROR)
{
LogMsg("Unable To Select Audio Context: %s", alcGetString(device, err));
return;
}
// Set Distance Model
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
// Mark As Loaded
loaded = true;
}
SoundSystemAL::~SoundSystemAL()
{
if (!loaded)
{
return;
}
// Delete Audio Sources
delete_sources();
// Delete Audio Buffers
delete_buffers();
// Deselect Context
alcMakeContextCurrent(NULL);
ALCenum err = alcGetError(device);
if (err != ALC_NO_ERROR)
{
LogMsg("Unable To Deselect Audio Context: %s", alcGetString(device, err));
}
// Destroy Context
alcDestroyContext(context);
err = alcGetError(device);
if (err != ALC_NO_ERROR)
{
LogMsg("Unable To Destroy Audio Context: %s", alcGetString(device, err));
}
// Close Device
alcCloseDevice(device);
// Can't check for error because device is closed
/*err = alcGetError(device);
if (err != ALC_NO_ERROR)
{
LogMsg("Unable To Close Audio Device: %s", alcGetString(device, err));
}*/
}
// Error Checking
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
#define AL_ERROR_CHECK_MANUAL(val) \
{ \
ALenum __err = val; \
if (__err != AL_NO_ERROR) \
{ \
LogMsg("(%s:%i) OpenAL Error: %s", __FILE__, __LINE__, alGetString(__err)); \
exit(EXIT_FAILURE); \
} \
}
// Delete Sources
void SoundSystemAL::delete_sources()
{
if (loaded)
{
for (ALuint source : idle_sources)
{
alDeleteSources(1, &source);
AL_ERROR_CHECK();
}
for (ALuint source : sources)
{
alDeleteSources(1, &source);
AL_ERROR_CHECK();
}
}
idle_sources.clear();
sources.clear();
}
// Delete Buffers
void SoundSystemAL::delete_buffers()
{
if (loaded)
{
for (auto &it : buffers)
{
if (it.second && alIsBuffer(it.second))
{
alDeleteBuffers(1, &it.second);
AL_ERROR_CHECK();
}
}
}
buffers.clear();
}
// Get Buffer
ALuint SoundSystemAL::get_buffer(const SoundDesc& sound)
{
if (buffers.count(sound.m_pData) > 0)
{
return buffers[sound.m_pData];
}
else
{
// Sound Format
ALenum format = AL_NONE;
if (sound.m_header.m_channels == 1)
{
format = sound.m_header.m_bytes_per_sample == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
}
else if (sound.m_header.m_channels == 2)
{
format = sound.m_header.m_bytes_per_sample == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8;
}
// Sound Data Size
int size = sound.m_header.m_channels * sound.m_header.m_length * sound.m_header.m_bytes_per_sample;
// Create Buffer
ALuint buffer;
alGenBuffers(1, &buffer);
AL_ERROR_CHECK();
alBufferData(buffer, format, sound.m_pData, size, sound.m_header.m_sample_rate);
AL_ERROR_CHECK();
// Store
buffers[sound.m_pData] = buffer;
return buffer;
}
}
bool SoundSystemAL::isAvailable()
{
return loaded;
}
void SoundSystemAL::setListenerPos(float x, float y, float z)
{
// Update Listener Position
alListener3f(AL_POSITION, x, y, z);
AL_ERROR_CHECK();
lastListenerPos = Vec3(x, y, z);
update();
}
void SoundSystemAL::setListenerAngle(float yaw, float pitch)
{
// Update Listener Orientation
float radian_yaw = yaw * (M_PI / 180);
ALfloat orientation[] = { -sinf(radian_yaw), 0.0f, cosf(radian_yaw), 0.0f, 1.0f, 0.0f };
alListenerfv(AL_ORIENTATION, orientation);
AL_ERROR_CHECK();
}
void SoundSystemAL::update()
{
// Check
if (!loaded)
{
return;
}
// Update Listener Volume
float volume = 1;
alListenerf(AL_GAIN, volume);
AL_ERROR_CHECK();
// Clear Finished Sources
std::vector<ALuint>::iterator it = sources.begin();
while (it != sources.end())
{
ALuint source = *it;
bool remove = false;
// Check
if (source && alIsSource(source))
{
// Is Valid Source
ALint source_state;
alGetSourcei(source, AL_SOURCE_STATE, &source_state);
AL_ERROR_CHECK();
if (source_state != AL_PLAYING)
{
// Finished Playing
remove = true;
if (idle_sources.size() < MAX_IDLE_SOURCES)
{
idle_sources.push_back(source);
}
else
{
alDeleteSources(1, &source);
AL_ERROR_CHECK();
}
}
}
else
{
// Not A Source
remove = true;
}
// Remove If Needed
if (remove) {
it = sources.erase(it);
}
else
{
++it;
}
}
}
void SoundSystemAL::playAt(const SoundDesc& sound, float x, float y, float z, float volume, float pitch)
{
// Check
if (!loaded)
{
return;
}
if (volume <= 0.0f)
return;
float distance = Vec3(x, y, z).distanceTo(lastListenerPos);
if (distance >= MAX_DISTANCE)
return;
// Load Sound
ALuint buffer = get_buffer(sound);
if (!buffer)
return;
// Get Source
ALuint al_source;
if (idle_sources.size() > 0)
{
// Use Idle Source
al_source = idle_sources.back();
idle_sources.pop_back();
}
else
{
// Create Source
alGenSources(1, &al_source);
// Special Out-Of-Memory Handling
{
ALenum err = alGetError();
if (err == AL_OUT_OF_MEMORY)
{
return;
}
else
{
AL_ERROR_CHECK_MANUAL(err);
}
}
}
bool isUi = AL_FALSE;
if (x == 0 && y == 0 && z == 0)
isUi = AL_TRUE;
// Set Properties
alSourcef(al_source, AL_PITCH, pitch);
AL_ERROR_CHECK();
alSourcef(al_source, AL_GAIN, volume);
AL_ERROR_CHECK();
alSource3f(al_source, AL_POSITION, x, y, z);
AL_ERROR_CHECK();
alSource3f(al_source, AL_VELOCITY, 0, 0, 0);
AL_ERROR_CHECK();
alSourcei(al_source, AL_LOOPING, AL_FALSE);
AL_ERROR_CHECK();
alSourcei(al_source, AL_SOURCE_RELATIVE, isUi);
AL_ERROR_CHECK();
// Set Attenuation
alSourcef(al_source, AL_MAX_DISTANCE, MAX_DISTANCE);
AL_ERROR_CHECK();
alSourcef(al_source, AL_ROLLOFF_FACTOR, 1.0f);
AL_ERROR_CHECK();
alSourcef(al_source, AL_REFERENCE_DISTANCE, 5.0f);
AL_ERROR_CHECK();
// Set Buffer
alSourcei(al_source, AL_BUFFER, buffer);
AL_ERROR_CHECK();
// Play
alSourcePlay(al_source);
AL_ERROR_CHECK();
sources.push_back(al_source);
}