diff --git a/Source/Engine/Audio/AudioBackendTools.h b/Source/Engine/Audio/AudioBackendTools.h index ea3b7c10b..04e784b06 100644 --- a/Source/Engine/Audio/AudioBackendTools.h +++ b/Source/Engine/Audio/AudioBackendTools.h @@ -161,7 +161,10 @@ public: case 2: default: // TODO: implement multi-channel support (eg. 5.1, 7.1) outputMatrix[0] = channels[FrontLeft]; - outputMatrix[sourceChannels + 1] = channels[FrontRight]; + if (sourceChannels == 1) + outputMatrix[1] = channels[FrontRight]; + else + outputMatrix[sourceChannels + 1] = channels[FrontRight]; break; } } diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp index 9730b6ddf..82abc8487 100644 --- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp +++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp @@ -40,11 +40,17 @@ namespace ALC { + struct SourceData + { + AudioDataInfo Format; + bool Spatial; + }; + ALCdevice* Device = nullptr; ALCcontext* Context = nullptr; AudioBackend::FeatureFlags Features = AudioBackend::FeatureFlags::None; CriticalSection Locker; - Dictionary SourceIDtoFormat; + Dictionary SourcesData; bool IsExtensionSupported(const char* extension) { @@ -88,32 +94,32 @@ namespace ALC alSourcef(sourceID, AL_PITCH, pitch); alSourcef(sourceID, AL_SEC_OFFSET, 0.0f); alSourcei(sourceID, AL_LOOPING, loop); - alSourcei(sourceID, AL_SOURCE_RELATIVE, !spatial); + alSourcei(sourceID, AL_SOURCE_RELATIVE, AL_TRUE); // Non-spatial sounds use AL_POSITION for panning alSourcei(sourceID, AL_BUFFER, 0); +#ifdef AL_SOFT_source_spatialize + alSourcei(sourceID, AL_SOURCE_SPATIALIZE_SOFT, AL_TRUE); // Always spatialize, fixes multi-channel played as spatial +#endif if (spatial) { -#ifdef AL_SOFT_source_spatialize - alSourcei(sourceID, AL_SOURCE_SPATIALIZE_SOFT, AL_TRUE); -#endif alSourcef(sourceID, AL_ROLLOFF_FACTOR, attenuation); alSourcef(sourceID, AL_DOPPLER_FACTOR, doppler); alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(minDistance)); alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position)); alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(Vector3::Zero)); +#ifdef AL_EXT_STEREO_ANGLES + const float panAngle = pan * PI_HALF; + const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians + alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles); +#endif } else { alSourcef(sourceID, AL_ROLLOFF_FACTOR, 0.0f); alSourcef(sourceID, AL_DOPPLER_FACTOR, 1.0f); alSourcef(sourceID, AL_REFERENCE_DISTANCE, 0.0f); - alSource3f(sourceID, AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(sourceID, AL_POSITION, pan, 0, -sqrtf(1.0f - pan * pan)); alSource3f(sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f); } -#ifdef AL_EXT_STEREO_ANGLES - const float panAngle = pan * PI_HALF; - const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians - alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles); -#endif } } @@ -303,7 +309,9 @@ uint32 AudioBackendOAL::Source_Add(const AudioDataInfo& format, const Vector3& p // Cache audio data format assigned on source (used in Source_GetCurrentBufferTime) ALC::Locker.Lock(); - ALC::SourceIDtoFormat[sourceID] = format; + auto& data = ALC::SourcesData[sourceID]; + data.Format = format; + data.Spatial = spatial; ALC::Locker.Unlock(); return sourceID; @@ -317,18 +325,30 @@ void AudioBackendOAL::Source_Remove(uint32 sourceID) ALC_CHECK_ERROR(alDeleteSources); ALC::Locker.Lock(); - ALC::SourceIDtoFormat.Remove(sourceID); + ALC::SourcesData.Remove(sourceID); ALC::Locker.Unlock(); } void AudioBackendOAL::Source_VelocityChanged(uint32 sourceID, const Vector3& velocity) { - alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(velocity)); + ALC::Locker.Lock(); + const bool spatial = ALC::SourcesData[sourceID].Spatial; + ALC::Locker.Unlock(); + if (spatial) + { + alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(velocity)); + } } void AudioBackendOAL::Source_TransformChanged(uint32 sourceID, const Vector3& position, const Quaternion& orientation) { - alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position)); + ALC::Locker.Lock(); + const bool spatial = ALC::SourcesData[sourceID].Spatial; + ALC::Locker.Unlock(); + if (spatial) + { + alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position)); + } } void AudioBackendOAL::Source_VolumeChanged(uint32 sourceID, float volume) @@ -343,11 +363,21 @@ void AudioBackendOAL::Source_PitchChanged(uint32 sourceID, float pitch) void AudioBackendOAL::Source_PanChanged(uint32 sourceID, float pan) { + ALC::Locker.Lock(); + const bool spatial = ALC::SourcesData[sourceID].Spatial; + ALC::Locker.Unlock(); + if (spatial) + { #ifdef AL_EXT_STEREO_ANGLES - const float panAngle = pan * PI_HALF; - const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians - alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles); + const float panAngle = pan * PI_HALF; + const ALfloat panAngles[2] = { (ALfloat)(PI / 6.0 - panAngle), (ALfloat)(-PI / 6.0 - panAngle) }; // Angles are specified counter-clockwise in radians + alSourcefv(sourceID, AL_STEREO_ANGLES, panAngles); #endif + } + else + { + alSource3f(sourceID, AL_POSITION, pan, 0, -sqrtf(1.0f - pan * pan)); + } } void AudioBackendOAL::Source_IsLoopingChanged(uint32 sourceID, bool loop) @@ -357,12 +387,8 @@ void AudioBackendOAL::Source_IsLoopingChanged(uint32 sourceID, bool loop) void AudioBackendOAL::Source_SpatialSetupChanged(uint32 sourceID, bool spatial, float attenuation, float minDistance, float doppler) { - alSourcei(sourceID, AL_SOURCE_RELATIVE, !spatial); if (spatial) { -#ifdef AL_SOFT_source_spatialize - alSourcei(sourceID, AL_SOURCE_SPATIALIZE_SOFT, AL_TRUE); -#endif alSourcef(sourceID, AL_ROLLOFF_FACTOR, attenuation); alSourcef(sourceID, AL_DOPPLER_FACTOR, doppler); alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(minDistance)); @@ -411,7 +437,7 @@ float AudioBackendOAL::Source_GetCurrentBufferTime(uint32 sourceID) alGetSourcef(sourceID, AL_SEC_OFFSET, &time); #else ALC::Locker.Lock(); - AudioDataInfo clipInfo = ALC::SourceIDtoFormat[sourceID]; + AudioDataInfo clipInfo = ALC::SourcesData[sourceID].Format; ALC::Locker.Unlock(); ALint samplesPlayed; alGetSourcei(sourceID, AL_SAMPLE_OFFSET, &samplesPlayed);