Open rkkoszewski opened 3 years ago
So it queued a buffer that was never filled with any data, which resulted in it having no real format, so the next real buffer to be queued didn't match the bad format. It might work better to disallow queueing a buffer that doesn't have a valid format (e.g. when SampleRate==0), though that could cause other issues depending on what the app is expecting.
Alternatively, ignore the format when it's invalid (and the buffer is empty, by implication) and allow queueing it anyway. But I'm hesitant on doing that since there could be places the format's used unexpectedly and cause problems if it's invalid or mismatched.
@kcat Is there some official documentation regarding what should be the exact behavior in OpenAL for this scenario? Given that this scenario is seems to be supported or somehow handled by the regular OpenAL implementation (From Creative?).
The spec says about alSourceQueueBuffers
:
All buffers in a queue must have the same format and attributes, with the exception of the
NULL buffer (i.e., 0) which can always be queued. An attempt to mix formats or other
buffer attributes will result in a failure and an AL_INVALID_VALUE error will be
thrown. If the queue operation fails, the source queue will remain unchanged (even if
some of the buffers could have been queued).
Regarding buffers, alGenBuffers
doesn't say anything about the initial format of the generated buffers, however the buffer attributes section lists the default values of the queryable buffer attributes. It specifies AL_FREQUENCY
defaults to 0, AL_BITS
defaults to 16, and AL_CHANNELS
defaults to 1. Although it also specifies these relate to the internal representation, which doesn't necessarily correlate to the format specified by alBufferData
or even specify a unique type (e.g. AL_BITS=8
could be unsigned 8-bit, or mulaw, or alaw).
OpenAL Soft is currently giving 8
by default for AL_BITS
which I guess should be fixed. But that wouldn't fix this issue since the sample rate/frequency being 0 is correct and would still cause it to fail.
I can't really guess what Creative's OpenAL is doing. Maybe it creates buffers with a 44100 sample rate by default instead of 0, and that just happens to let it work. Or maybe it ignores the format if the buffer has no samples. It's also possible it ignores the sample rate altogether when checking for a matching format. All of these possibilities would be bugs, but some would be easier to deal with than others.
So to follow up on this issue. It indeed seems that each time the Frequency shows up as 0 in the game, BufferFmt->mSampleLen also returns 0. So from what I understand from it is that there is effectively an empty audio sample getting queued. Skipping the fmt_mismatch checks when mSampleLen is 0 seems to work fine and no sounds are getting skipped anymore. Perhaps that's what is referred in the spec as "(i.e., 0)"?
In essence adding this:
...
if(BufferFmt == nullptr)
BufferFmt = buffer;
else if(BufferFmt->mSampleLen != 0)
{
fmt_mismatch |= BufferFmt->mSampleRate != buffer->mSampleRate;
fmt_mismatch |= BufferFmt->mChannels != buffer->mChannels;
if(BufferFmt->isBFormat())
...
Would such a change be accepted in OpenAL-Soft?
It indeed seems that each time the Frequency shows up as 0 in the game, BufferFmt->mSampleLen also returns 0.
Yes, because if Frequency is 0, alBufferData
was never called (as it requires a positive, non-0 frequency), so mSampleLen must then be 0.
Skipping the fmt_mismatch checks when mSampleLen is 0 seems to work fine and no sounds are getting skipped anymore. Perhaps that's what is referred in the spec as "(i.e., 0)"?
No, the "NULL buffer (i.e., 0)" is referring to buffer ID 0
. Something like this:
ALuint id = 0;
alSourceQueueBuffers(source, 1, &id);
is allowed and will always work, despite the buffer having no format. It will increase the queued buffer count, and become processed and gets returned when unqueued as expected.
Would such a change be accepted in OpenAL-Soft?
Maybe something like it. I'd prefer to keep the scope of non-standard API behavior as minimal as possible, in case some issues pop up that would need changing behavior that apps have come to expect. I might even want to put it behind an env var compatibility toggle, so unsuspecting new apps can't end up depending on it accidentally. At most, I may allow a 0-frequency buffer to be unconditionally queued like the null buffer, but I'd prefer to get a better idea of how Creative's driver handled that first -- that is, whether Creative erroneously defaults buffers to 44100hz instead of 0, or if it ignores the format when the sample rate is 0, or if it ignores the format when the buffer length is 0 (or if it even allows calling alBufferData
with a 0 length buffer).
Perhaps a good approach could be to exercise some tests with the DLL from Creative to see it's behavior. The file is called DefOpenAL32.dll, but it can be renamed to OpenAL32.dll and used as any other OpenAL implementation. Unreal Tournament 2004 seems to be using the same DLL also and probably many more UT2 games. The file (MD5) hash from the game DLL in SWAT 4 is: EF595453582229F0E7B30A6EDE1BFD64 and it seems to be available for download from here: https://www.pconlife.com/download/otherfile/172916/ef595453582229f0e7b30a6ede1bfd64/
I'm not sure if I'll be able to help much with this though, as I don't have any experience with OpenAL, but perhaps I could tinker with the alPlay example and adapt it.
There's actually two DLLs from Creative... wrap_oal.dll
implements a software mixer and a wrapper over DirectSound3D, and ct_oal.dll
which is a hardware implementation for their cards. Older versions of wrap_oal.dll
were actually open source, and looking at that source, there's no provisions for an unfilled buffer being queueable. A newly generated buffer struct is cleared to 0s, and queueing a buffer checks its sample rate and format against what's already queued, like OpenAL Soft. Unless this was changed later on, or if it's using a hardware driver that's more lenient, it should fail.
When I get the time, I'll do what I can to test the wrapper driver, but I won't be able to test the hardware driver since I don't have the hardware (or Windows for that matter).
Unreal Engine 2 widely used "DefOpenAL32.dll" IS wrap_oal (and you can track on Windows systems some really early builds, like the Jedi Outcast one, perhaps the first existing). When you choose in the ini file the "default" driver DefOpenAL32.dll is used as "Generic Software" OpenAL implementation, acting as a wrapper over a DirectSound device.
When you set it to "false" the engine looks for other implementations, typically ct_oal by Creative that can give you "hardware accelerated" OpenAL (today too, if working - like Audigy 2 ct_oal ).
Swat 4 Elite Force and Original Game(GOG) Works voice clips. To run with mod. You need to copy the file from X:\SWAT 4\Content\System\DefOpenAL32.dll. To the mod folder X:\SWAT 4\SEF\System. And the last step is to copy from the DSOAL archive. alsoft_error.txt dsoal_error.txt
I don't suppose this works now with commit 9fd9fee35ce5657b07086652b255e2dfbc49b435?
Edit- Or rather, commit ff620411a75a3b27f6a449367021b07e5b700d0c since that previous commit had the wrong check.
Friendly ping, just because
p.s. technically speaking not using the default driver should just have UE2 games search for the normal "OpenAL32.dll" router, they don't themselves look for the implementations then
Hi, using OpenAL-Soft with SWAT 4 seems to work fine to a certain degree. The only problem seems to be that there are some sounds that are not playing. In the game menu it seems that some sounds are not playing randomly, like background sounds effects or clicking on the menu items sometimes plays a sound and sometimes not. In other cases, during gameplay when giving the team an order, that sound is never playing while other game sounds seems to keep playing perfectly fine.
Setting OpenAL-Soft to verbose I could observe that there are numerous "Queueing buffer with mismatched format" errors shown in the logs which could be the dropped sounds. Any idea what could be going on there?
Here is an older video with the missing sounds when giving orders: https://www.youtube.com/watch?v=SOYYkuZfn8s
Here is the full log (I tried to test with Mono in case 3D audio was the issue in this case):
EDIT 1: I added some more debugging to openal-soft to see what is mismatching in the logs. It seems that the SampleRate is 0 and the OriginalType is also different. Here is the exerpt of the log:
EDIT 2: Disabling the "fmt_mismatch" check by setting it to always be "false" effectively fixes the issue with the missing sounds. The game seems to be running stable.