Page 1 of 31

ZDoom with OpenAL

Posted: Sun Sep 14, 2008 6:22 am
by Chris
Decided to take today and see how well I could get ZDoom working with OpenAL. Attached is the result (based on the 2.2.0 sources, but I'll update as needed, if anyone cares).

On Linux using OpenAL Soft, it seems to work great. Full 3D/surround sound, and "local" sounds, working. Streaming and non-DMX formats aren't yet working, though I'll probably be getting to them next, if this really interests anyone. Further, I can probably get environmental effects working using EFX, which should also work on software devices (unlike FMOD, which only seems to provide EAX when hardware is there).

The attached zip contains oalsound.cpp/h (place in src/sound/) and a small diff for src/sound/i_sound.cpp. For Makefile.linux, add openal to the pkg-config commands so that you have:
CFLAGS += -MMD -DHAVE_FILELENGTH -D__forceinline=inline `sdl-config --cflags` `pkg-config gtk+-2.0 openal --cflags`
LDFLAGS += -lFLAC++ -lFLAC -lz -ljpeg -lfmod `sdl-config --libs` `pkg-config gtk+-2.0 openal --libs`

For Windows, make sure you download the OpenAL SDK, and add -lopenal32 to the LDFLAGS Makefile.mingw, or add openal32.lib to the MSVC project.

Re: ZDoom with OpenAL

Posted: Sun Sep 14, 2008 7:22 am
by TheDarkArchon
Heh, long time no see there. Where have you been hiding over the past few months?

Also, paging Graf to this thread. Repeat, paging Graf to this thread.

Just to reiterate that, paging Graf to this thread.

Re: ZDoom with OpenAL

Posted: Sun Sep 14, 2008 8:27 am
by Graf Zahl
Basing this on 2.2.0 makes it a futile exercise. The low level sound interface has changed so much that almost nothing works directly. If you can port this to the latest revisions it would be really great because it's exactly what I need for a GPL GZDoom.

Re: ZDoom with OpenAL

Posted: Sun Sep 14, 2008 3:58 pm
by Chris
Heh, long time no see there. Where have you been hiding over the past few months?
Got pulled away to more "modern" games, since I finally got a computer that could handle them. But recently I've had an itch to come back and play Doom/Heretic/Hexen again. :)

And I'll see what I can do about bringing it up against the latest SVN today.

EDIT:
Seems someone is currently doing work on the tree. I got it roughly moved over to SVN, and it wouldn't start a game (it froze on level load), updated, and now it won't compile. I'll wait a bit to try again, but just in case anyone's curious, these are the errors:

Code: Select all

zdoom/src/./basictypes.h:98:7: warning: no newline at end of file
zdoom/src/sdl/i_input.cpp: In function ‘void PostMouseMove(int, int)’:
zdoom/src/sdl/i_input.cpp:240: error: variable ‘event_t ev’ has initializer but incomplete type
zdoom/src/sdl/i_input.cpp:256: error: ‘EV_Mouse’ was not declared in this scope
zdoom/src/sdl/i_input.cpp: In function ‘void MessagePump(const SDL_Event&)’:
zdoom/src/sdl/i_input.cpp:333: error: variable ‘event_t event’ has initializer but incomplete type
zdoom/src/sdl/i_input.cpp:359: error: ‘EV_KeyDown’ was not declared in this scope
zdoom/src/sdl/i_input.cpp:359: error: ‘EV_KeyUp’ was not declared in this scope
zdoom/src/sdl/i_input.cpp:393: error: ‘EV_GUI_Event’ was not declared in this scope

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 2:31 am
by Chris
This try is against SVN r1225. I'm running into several issues, though. Some problems revolve around the use of FMOD's callbacks (mainly how it changes the associated FSoundChan when the sound playback ends asynchronously.. which is kind of evil, IMO). The callback for the rolloff is pretty evil as well, since no other API that I know of does it that way.. OpenAL in particular has a per-source rolloff factor, but a global distance model/rolloff type, and only predefined types (linear, inverse distance, exponent, and none). The rest of the problems seem to be because of changes the renderer needs to do to various structs its given, with not much info on who needs to change what, where, when and why.

Currently 2D sounds seem to work mostly alright. But the 3D sounds will eventually just stop as if its running out of channels (though 2D sounds will continue to work). As well, after going in-game, some 2D sounds will pan (which is odd to say the least because PlaySound doesn't take a panning parameter..).
EDIT: Figures I made a breakthrough with this just after I posted. 2D sounds seem to work fine, as do most 3D sounds, but some will still sometimes cutout for a bit, and come back. I might be able to fix this, but for now I'm just updating the zip.

The zip contains what's needed to get ZDoom compiling under Linux again, as well as the patches to CMakeLists.txt, i_sound.cpp, and the new oalsound files. If anyone could help me understand what's wrong, I'd be quite appreciative.

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 5:09 am
by Graf Zahl
Chris wrote:This try is against SVN r1225. I'm running into several issues, though. Some problems revolve around the use of FMOD's callbacks (mainly how it changes the associated FSoundChan when the sound playback ends asynchronously.. which is kind of evil, IMO).
I tried to separate this code into proper low/high level parts but it's so messy that my first attempts failed. :(
The callback for the rolloff is pretty evil as well, since no other API that I know of does it that way.. OpenAL in particular has a per-source rolloff factor, but a global distance model/rolloff type, and only predefined types (linear, inverse distance, exponent, and none).
I'm afraid that this callback's functionality is necessary. It is essential for Doom's sound to work properly. Randy's first FmodEx version uses the stock rolloff calculations as well and it was horrible.

Chris wrote:The rest of the problems seem to be because of changes the renderer needs to do to various structs its given, with not much info on who needs to change what, where, when and why.
According to Randy this was so he 'doesn't need to jump through hoops.' I have been fighting against this sloppy organization for the last 2 weeks and I'm still not done separating the true interface code from improperly placed code. A few things I tried resulted in unexpected errors.

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 7:41 am
by Chris
Graf Zahl wrote:
Chris wrote:The callback for the rolloff is pretty evil as well, since no other API that I know of does it that way.. OpenAL in particular has a per-source rolloff factor, but a global distance model/rolloff type, and only predefined types (linear, inverse distance, exponent, and none).
I'm afraid that this callback's functionality is necessary. It is essential for Doom's sound to work properly. Randy's first FmodEx version uses the stock rolloff calculations as well and it was horrible.
I suppose. I was able to make a work around that hopefully shouldn't impose too much on CPU time. OpenAL's distance attenuation is disabled, while SoundRenderer::UpdateSounds goes through the list of all allocated channels. For each one that has an in-use and non-local source, it gets the distance from the listener, calculates the attenuation, then sets it as the source gain.

For this, I'm thinking I might propose an OpenAL extension to provide essentially what S_SoundCurve is for (an array of mulipliers that's used to get attenuation between min dist and max dist). A callback would be more fitting, but those don't go over so well between different languages and language bindings, nor does it seem to be OpenAL's "style". I notice though, that each sound is given its own rolloff type (or at least, a type passed to each PlaySound3D call). Is it expected that different sounds can have different rolloff types, or is it just passed for no real reason? If the latter, I think it may be a better idea to pass the type once beforehand, and just the min dist and max dist/rolloff factor for PlaySound3D (to avoid this kind of confusion). If the former, then I think OpenAL will need another extension for that.

It seems most of the sound issues are taken care of for now, though. I don't notice any anamolies with it in Heretic, although Hexen still has a habit of losing sounds (particularly in the first level). Updated oalsound.cpp attached. Properly handling priorities and killing lowest-priority sounds may help, but I'll need to do some testing with it (I didn't have this issue with 2.2.0, so it doesn't strike me that I'm using all 12 channels at start, especially when I don't hear anything).
According to Randy this was so he 'doesn't need to jump through hoops.' I have been fighting against this sloppy organization for the last 2 weeks and I'm still not done separating the true interface code from improperly placed code. A few things I tried resulted in unexpected errors.
Unfortunately it's making me jump through hoops, and causing a bit of code duplication. :P

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 7:56 am
by Graf Zahl
Chris wrote:
According to Randy this was so he 'doesn't need to jump through hoops.' I have been fighting against this sloppy organization for the last 2 weeks and I'm still not done separating the true interface code from improperly placed code. A few things I tried resulted in unexpected errors.
Unfortunately it's making me jump through hoops, and causing a bit of code duplication. :P

Don't tell me. ;)

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 12:23 pm
by Graf Zahl
I just finished cleaning up the low level sound interface. No more messing around with high level flags and such stuff. Unfortunately this means that I can't use your code anymore as it is.

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 4:18 pm
by randi
Chris wrote:Some problems revolve around the use of FMOD's callbacks (mainly how it changes the associated FSoundChan when the sound playback ends asynchronously.. which is kind of evil, IMO).
FMOD Ex guarantees that callbacks only run when you update the system object, so they are never run asynchronously.

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 5:13 pm
by Graf Zahl
Good to know. I had concerns with a few changes I made today but this means that it won't cause any problems.

Re: ZDoom with OpenAL

Posted: Mon Sep 15, 2008 7:56 pm
by Chris
Graf Zahl wrote:Unfortunately this means that I can't use your code anymore as it is.
These changes were easier than last time, at least. And it seems the missing sounds problem was due to running out of channels. I increased snd_channels from 12 to 32, and I'm not losing sounds in Hexen anymore. So as it seems, what I have done with the OpenAL backend works as expected. I just need to finish implementing the rest (pausing sounds, non-raw loading, streaming..), which I'll be getting to. Patch attached.
randy wrote:FMOD Ex guarantees that callbacks only run when you update the system object, so they are never run asynchronously.
It also seems it's run when you explicitly call the stop() method.

EDIT: And before I forget *again*, it seems sound isn't shutdown when quitting. The buffers are properly deleted, but the sound renderer object isn't deleted.

Re: ZDoom with OpenAL

Posted: Tue Sep 16, 2008 12:42 am
by Graf Zahl
Chris wrote: EDIT: And before I forget *again*, it seems sound isn't shutdown when quitting. The buffers are properly deleted, but the sound renderer object isn't deleted.
Is this about your OpenAL code or FMOD?


One more thing: If your code becomes stable enough we will need a mechanism that allows to distribute ZDoom with only one of the needed sound libraries. On Windows I can write the code to dynamically reference the functions from DLLs but on Linux I have no idea how to do it.

Re: ZDoom with OpenAL

Posted: Tue Sep 16, 2008 1:33 am
by Chris
Graf Zahl wrote:
Chris wrote: EDIT: And before I forget *again*, it seems sound isn't shutdown when quitting. The buffers are properly deleted, but the sound renderer object isn't deleted.
Is this about your OpenAL code or FMOD?
Either. It seems it's not deleting the GSnd object because the destructor isn't being run.
One more thing: If your code becomes stable enough we will need a mechanism that allows to distribute ZDoom with only one of the needed sound libraries. On Windows I can write the code to dynamically reference the functions from DLLs but on Linux I have no idea how to do it.
Getting functions from a dynamic lib in Linux is nearly the same. Just instead of doing:

Code: Select all

HANDLE handle = LoadLibrary("foo.dll");
func = GetProcAddress(handle, "funcname");
if(!func) error();
You do:

Code: Select all

void *handle = dlopen("foo.so", RTLD_NOW); // RTLD_NOW means to resolve all symbols used by the lib before returning
func = dlsym(handle, "funcname");
if(dlerror() != NULL) error(); // dlerror returns a const char* to a string description of the last error, then clears the last error, or NULL for no error
.. being sure to include dlfcn.h and link with libdl. In the case of OpenAL, you'd load libopenal.so.1 in Linux (or libopenal.so.0 for the old SI, but generally you'd want to avoid that..).


Today, I was able to get CreateStream working. I also cleaned up a bit of the left-over flag-handling code in the renderer. Latest is attached.

Re: ZDoom with OpenAL

Posted: Wed Sep 17, 2008 2:05 am
by Chris
I have a question about S_GetRolloff. Was this intended?

Code: Select all

        float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance);
        if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve != NULL)
        {
                volume = S_SoundCurve[int(S_SoundCurveSize * (1 - volume))] / 127.f;
        }
        if (rolloff->RolloffType == ROLLOFF_Linear)
        {
                return volume;
        }
        else
        {
                return (powf(10.f, volume) - 1.f) / 9.f;
        }
This applies the powf() on the S_SoundCurve result for custom rolloffs.