diff options
-rw-r--r-- | al/source.cpp | 144 | ||||
-rw-r--r-- | al/source.h | 2 | ||||
-rw-r--r-- | alc/alc.cpp | 3 | ||||
-rw-r--r-- | alc/context.cpp | 50 | ||||
-rw-r--r-- | alc/context.h | 4 | ||||
-rw-r--r-- | alsoftrc.sample | 7 | ||||
-rw-r--r-- | docs/env-vars.txt | 6 |
7 files changed, 188 insertions, 28 deletions
diff --git a/al/source.cpp b/al/source.cpp index b1406326..d30a7094 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -77,6 +77,8 @@ #include <cassert> #endif // ALSOFT_EAX +bool sBufferSubDataCompat{false}; + namespace { using namespace std::placeholders; @@ -1006,6 +1008,10 @@ enum SourceProp : ALenum { /* AL_SOFT_UHJ */ srcStereoMode = AL_STEREO_MODE_SOFT, srcSuperStereoWidth = AL_SUPER_STEREO_WIDTH_SOFT, + + /* AL_SOFT_buffer_sub_data */ + srcByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, + srcSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, }; @@ -1037,6 +1043,10 @@ constexpr ALuint IntValsByProp(ALenum prop) case AL_STEREO_MODE_SOFT: return 1; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + return 2; + /*fall-through*/ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: case AL_PITCH: @@ -1052,11 +1062,15 @@ constexpr ALuint IntValsByProp(ALenum prop) case AL_CONE_OUTER_GAINHF: case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: case AL_SEC_LENGTH_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: return 1; /* 1x float */ + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + return 2; + break; + case AL_AUXILIARY_SEND_FILTER: return 3; @@ -1106,6 +1120,10 @@ constexpr ALuint Int64ValsByProp(ALenum prop) case AL_STEREO_MODE_SOFT: return 1; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + return 2; + /*fall-through*/ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: case AL_PITCH: @@ -1121,11 +1139,15 @@ constexpr ALuint Int64ValsByProp(ALenum prop) case AL_CONE_OUTER_GAINHF: case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: case AL_SEC_LENGTH_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: return 1; /* 1x float */ + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + return 2; + break; + case AL_SAMPLE_OFFSET_LATENCY_SOFT: case AL_SAMPLE_OFFSET_CLOCK_SOFT: case AL_STEREO_ANGLES: @@ -1182,7 +1204,6 @@ constexpr ALuint FloatValsByProp(ALenum prop) case AL_BUFFERS_QUEUED: case AL_BUFFERS_PROCESSED: case AL_SOURCE_TYPE: - case AL_SOURCE_RADIUS: case AL_SOURCE_RESAMPLER_SOFT: case AL_SOURCE_SPATIALIZE_SOFT: case AL_BYTE_LENGTH_SOFT: @@ -1192,6 +1213,13 @@ constexpr ALuint FloatValsByProp(ALenum prop) case AL_SUPER_STEREO_WIDTH_SOFT: return 1; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(!sBufferSubDataCompat) + return 1; + /*fall-through*/ + case AL_SAMPLE_RW_OFFSETS_SOFT: + break; + case AL_STEREO_ANGLES: return 2; @@ -1249,7 +1277,6 @@ constexpr ALuint DoubleValsByProp(ALenum prop) case AL_BUFFERS_QUEUED: case AL_BUFFERS_PROCESSED: case AL_SOURCE_TYPE: - case AL_SOURCE_RADIUS: case AL_SOURCE_RESAMPLER_SOFT: case AL_SOURCE_SPATIALIZE_SOFT: case AL_BYTE_LENGTH_SOFT: @@ -1259,6 +1286,13 @@ constexpr ALuint DoubleValsByProp(ALenum prop) case AL_SUPER_STEREO_WIDTH_SOFT: return 1; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(!sBufferSubDataCompat) + return 1; + /*fall-through*/ + case AL_SAMPLE_RW_OFFSETS_SOFT: + break; + case AL_SEC_OFFSET_LATENCY_SOFT: case AL_SEC_OFFSET_CLOCK_SOFT: case AL_STEREO_ANGLES: @@ -1499,7 +1533,12 @@ try { Source->Offset = values[0]; return; - case AL_SOURCE_RADIUS: + case AL_SAMPLE_RW_OFFSETS_SOFT: + break; + + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + break; CheckSize(1); CheckValue(values[0] >= 0.0f && std::isfinite(values[0])); @@ -1889,6 +1928,19 @@ try { return; + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + /* Query only */ + return Context->setError(AL_INVALID_OPERATION, + "Setting read-only source property 0x%04x", prop); + break; + + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + return Context->setError(AL_INVALID_OPERATION, + "Setting read-only source property 0x%04x", prop); + /*fall-through*/ + /* 1x float */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: @@ -1904,7 +1956,6 @@ try { case AL_CONE_OUTER_GAINHF: case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: case AL_SEC_LENGTH_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: CheckSize(1); @@ -2009,6 +2060,21 @@ try { ivals[2] = static_cast<int>(values[2]); return SetSourceiv(Source, Context, prop, {ivals, 3u}); + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + { + /* Query only */ + return Context->setError(AL_INVALID_OPERATION, + "Setting read-only source property 0x%04x", prop); + } + break; + + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + return Context->setError(AL_INVALID_OPERATION, + "Setting read-only source property 0x%04x", prop); + /*fall-through*/ + /* 1x float */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: @@ -2024,7 +2090,6 @@ try { case AL_CONE_OUTER_GAINHF: case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: case AL_SEC_LENGTH_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: CheckSize(1); @@ -2170,7 +2235,12 @@ try { values[0] = Source->DopplerFactor; return true; - case AL_SOURCE_RADIUS: + case AL_SAMPLE_RW_OFFSETS_SOFT: + break; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + break; + CheckSize(1); values[0] = Source->Radius; return true; @@ -2423,6 +2493,35 @@ try { values[0] = EnumFromStereoMode(Source->mStereoMode); return true; + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + { + CheckSize(2); + const auto offset = GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context); + /* FIXME: values[1] should be ahead of values[0] by the device + * update time. It needs to clamp or wrap the length of the buffer + * queue. + */ + values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max())); + values[1] = values[0]; + return true; + } + break; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + { + CheckSize(2); + const auto offset = GetSourceOffset(Source, AL_BYTE_OFFSET, Context); + /* FIXME: values[1] should be ahead of values[0] by the device + * update time. It needs to clamp or wrap the length of the buffer + * queue. + */ + values[0] = static_cast<int>(mind(offset, std::numeric_limits<int>::max())); + values[1] = values[0]; + return true; + } + /*fall-through*/ + /* 1x float/double */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: @@ -2441,7 +2540,6 @@ try { case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: case AL_CONE_OUTER_GAINHF: - case AL_SOURCE_RADIUS: case AL_SUPER_STEREO_WIDTH_SOFT: CheckSize(1); if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) @@ -2545,6 +2643,33 @@ try { values[1] = srcclock.count(); return true; + case AL_SAMPLE_RW_OFFSETS_SOFT: + if(sBufferSubDataCompat) + { + CheckSize(2); + /* FIXME: values[1] should be ahead of values[0] by the device + * update time. It needs to clamp or wrap the length of the buffer + * queue. + */ + values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_SAMPLE_OFFSET, Context)); + values[1] = values[0]; + return true; + } + break; + case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ + if(sBufferSubDataCompat) + { + CheckSize(2); + /* FIXME: values[1] should be ahead of values[0] by the device + * update time. It needs to clamp or wrap the length of the buffer + * queue. + */ + values[0] = static_cast<int64_t>(GetSourceOffset(Source, AL_BYTE_OFFSET, Context)); + values[1] = values[0]; + return true; + } + /*fall-through*/ + /* 1x float/double */ case AL_CONE_INNER_ANGLE: case AL_CONE_OUTER_ANGLE: @@ -2563,7 +2688,6 @@ try { case AL_AIR_ABSORPTION_FACTOR: case AL_ROOM_ROLLOFF_FACTOR: case AL_CONE_OUTER_GAINHF: - case AL_SOURCE_RADIUS: case AL_SUPER_STEREO_WIDTH_SOFT: CheckSize(1); if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) diff --git a/al/source.h b/al/source.h index 0882288c..ac97c8a7 100644 --- a/al/source.h +++ b/al/source.h @@ -41,6 +41,8 @@ enum class SourceStereo : bool { #define INVALID_VOICE_IDX static_cast<ALuint>(-1) +extern bool sBufferSubDataCompat; + struct ALbufferQueueItem : public VoiceBufferItem { ALbuffer *mBuffer{nullptr}; diff --git a/alc/alc.cpp b/alc/alc.cpp index 1a4a89ad..bb83e1f7 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -455,6 +455,8 @@ const struct { DECL(alSourcePlayAtTimeSOFT), DECL(alSourcePlayAtTimevSOFT), + + DECL(alBufferSubDataSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -1158,6 +1160,7 @@ void alc_initconfig(void) } return GetConfigValueBool(nullptr, "game_compat", optname, false); }; + sBufferSubDataCompat = checkflag("__ALSOFT_ENABLE_SUB_DATA_EXT", "enable-sub-data-ext"); compatflags.set(CompatFlags::ReverseX, checkflag("__ALSOFT_REVERSE_X", "reverse-x")); compatflags.set(CompatFlags::ReverseY, checkflag("__ALSOFT_REVERSE_Y", "reverse-y")); compatflags.set(CompatFlags::ReverseZ, checkflag("__ALSOFT_REVERSE_Z", "reverse-z")); diff --git a/alc/context.cpp b/alc/context.cpp index cb2410f4..65689a5b 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -171,6 +171,20 @@ void ALCcontext::init() mExtensionList = alExtList; + if(sBufferSubDataCompat) + { + std::string extlist{mExtensionList}; + + const auto pos = extlist.find("AL_EXT_SOURCE_RADIUS "); + if(pos != std::string::npos) + extlist.replace(pos, 20, "AL_SOFT_buffer_sub_data"); + else + extlist += " AL_SOFT_buffer_sub_data"; + + mExtensionListOverride = std::move(extlist); + mExtensionList = mExtensionListOverride.c_str(); + } + #ifdef ALSOFT_EAX eax_initialize_extensions(); #endif // ALSOFT_EAX @@ -441,30 +455,34 @@ void ALCcontext::eax_initialize_extensions() std::strlen(eax5_ext_name) + 1 + std::strlen(eax_x_ram_ext_name) + 1; - mEaxExtensionList.reserve(string_max_capacity); + std::string extlist; + extlist.reserve(string_max_capacity); - if(eaxIsCapable()) { - mEaxExtensionList += eax1_ext_name; - mEaxExtensionList += ' '; + if(eaxIsCapable()) + { + extlist += eax1_ext_name; + extlist += ' '; - mEaxExtensionList += eax2_ext_name; - mEaxExtensionList += ' '; + extlist += eax2_ext_name; + extlist += ' '; - mEaxExtensionList += eax3_ext_name; - mEaxExtensionList += ' '; + extlist += eax3_ext_name; + extlist += ' '; - mEaxExtensionList += eax4_ext_name; - mEaxExtensionList += ' '; + extlist += eax4_ext_name; + extlist += ' '; - mEaxExtensionList += eax5_ext_name; - mEaxExtensionList += ' '; + extlist += eax5_ext_name; + extlist += ' '; } - mEaxExtensionList += eax_x_ram_ext_name; - mEaxExtensionList += ' '; + extlist += eax_x_ram_ext_name; + extlist += ' '; + + extlist += mExtensionList; - mEaxExtensionList += mExtensionList; - mExtensionList = mEaxExtensionList.c_str(); + mExtensionListOverride = std::move(extlist); + mExtensionList = mExtensionListOverride.c_str(); } void ALCcontext::eax_initialize() diff --git a/alc/context.h b/alc/context.h index 926a76a4..e8efdbf1 100644 --- a/alc/context.h +++ b/alc/context.h @@ -103,6 +103,8 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext>, ContextBase { const char *mExtensionList{nullptr}; + std::string mExtensionListOverride{}; + ALCcontext(al::intrusive_ptr<ALCdevice> device); ALCcontext(const ALCcontext&) = delete; @@ -401,8 +403,6 @@ private: Eax5Props mEax{}; // Current EAX state. EAXSESSIONPROPERTIES mEaxSession{}; - std::string mEaxExtensionList{}; - [[noreturn]] static void eax_fail(const char* message); [[noreturn]] static void eax_fail_unknown_property_set_id(); [[noreturn]] static void eax_fail_unknown_primary_fx_slot_id(); diff --git a/alsoftrc.sample b/alsoftrc.sample index d894791e..2906cca4 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -646,6 +646,13 @@ # kilometer per unit, a value of 1000 will correctly adjust the filters. #nfc-scale = 1 +## enable-sub-data-ext: (global) +# Enables the AL_SOFT_buffer_sub_data extension, disabling the +# AL_EXT_SOURCE_RADIUS extension. These extensions are incompatible, so only +# one can be available. The latter extension is more commonly used, but this +# option can be enabled for older apps that want the former extension. +#enable-sub-data-ext = false + ## reverse-x: (global) # Reverses the local X (left-right) position of 3D sound sources. #reverse-x = false diff --git a/docs/env-vars.txt b/docs/env-vars.txt index 77a30c58..815a3098 100644 --- a/docs/env-vars.txt +++ b/docs/env-vars.txt @@ -58,6 +58,12 @@ between 0 and 180 degrees, instead of the expected range of 0 to 360 degrees. Setting this to "true" or "1" restores the old buggy behavior, for apps that were written to expect the incorrect range. +__ALSOFT_ENABLE_SUB_DATA_EXT +The more widely used AL_EXT_SOURCE_RADIUS extension is incompatible with the +now-defunct AL_SOFT_buffer_sub_data extension. Setting this to "true" or "1" +restores the AL_SOFT_buffer_sub_data extension for apps that require it, +disabling AL_EXT_SOURCE_RADIUS. + __ALSOFT_REVERSE_Z Applications that don't natively use OpenAL's coordinate system have to convert to it before passing in 3D coordinates. Depending on how exactly this is done, |