mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-17 20:10:23 +03:00
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:
323
platforms/openal/SoundSystemAL.cpp
Normal file
323
platforms/openal/SoundSystemAL.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user