aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/source.cpp144
-rw-r--r--al/source.h2
-rw-r--r--alc/alc.cpp3
-rw-r--r--alc/context.cpp50
-rw-r--r--alc/context.h4
-rw-r--r--alsoftrc.sample7
-rw-r--r--docs/env-vars.txt6
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,