Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
FAudio for Proton
Proton 3.16-5 ships with FAudio as its XAudio2/X3DAudio/XAPOFX/XACT3 implementation. It is introduced as a Linux-native library that is accessed by Wine, with the Wine XAudio source now acting as a very thin wrapper containing the absolute minimum code necessary to make FAudio work in Wine's environment.
The expectation is that Wine's side is going to change very little, as 99% of the code is just calling FAudio with the parameters given by the application, entirely unmodified. The "real" work is in one of two things:
- Parameter modifications for version compatibility. For example, OnVoiceProcessingPassStart has no parameters in version 2.0 and one parameter in 2.1+.
- Audio engine processing is deferred to a Wine thread. XAudio2 can call application code via callbacks, and the SDL audio thread is not prepared for Wine's environment.
The real meat of the new audio system is, as you'd expect, in FAudio itself. This is nice in that you only need to update libFAudio.so to make changes (unless you're breaking the API for some reason?), allowing for fast iteration/debugging/testing.
To help users who are interested in playing with FAudio, here is a quick guide for building and running FAudio with various features that aren't present in a Release version of the library.
Part 0: ELI5
FAudio is a library that acts like Microsoft's XAudio. XAudio is a low-level audio library used on Windows, Xbox 360, and Xbox One. FAudio mimics the XAudio API as closely as possible, so existing XAudio code does not have to change (much).
Usually Linux games use OpenAL. OpenAL is great, but does not fit well for mimicking XAudio. Think of it like this: If OpenAL is like Audio OpenGL, FAudio is more like Audio Vulkan.
Reimplementing XAudio was a lot easier than you might think, because it's much lower-level than other audio libraries! And much like OpenGL->Vulkan, it has similar upsides/downsides. FAudio was relatively easy for one person to write and has so far been easy for others to understand, but the downside is that if something goes wrong, lots of bad things can happen (somewhat by design). You may experience hard crashes, or worse, hideous screeching sounds coming out of your speakers/headphones.
My hope is that the user data from Proton will help us make FAudio more accurate, allowing for more games to get whitelisted on Steam Play, meaning more games to play on Linux! And because FAudio is a separate project, it can also be used to port XAudio-based games to Linux as native applications.
Part 1: Building FAudio
FAudio has only three requirements:
- C compiler (GCC and Clang are both known to work)
- SDL 2.0.9
An optional fourth requirement is FFmpeg, for WMA support.
To download and compile FAudio via Git:
git clone git://github.com/FNA-XNA/FAudio.git cd FAudio mkdir flibitBuild cd flibitBuild cmake .. make # This is for 32-bit support mkdir ../flibitBuild32 cd ../flibitBuild32 cmake .. -DCMAKE_C_FLAGS="-m32" make
Part 2: Installing FAudio (Proton)
Copy your libFAudio.so.0 to the Proton dist's lib/lib64 folder. For example:
cp libFAudio.so.0 ~/.local/share/Steam/steamapps/common/Proton\ 3.16/dist/lib64/
Yeah, that's really it. A bit easier than a Wine rebuild, no? If you want to go back to the official build, you can extract it from
proton_dist.tar.gz, found in the Proton folder.
Part 3: Anything else?
Not really! The above directions will give you a standard Release build of FAudio. But we want all the fancy stuff, right?
Here are the options you care about:
FFMPEG: Build with FFmpeg support, needed for WMA decoding
LOG_ASSERTIONS: Instead of a graphical assert dialog, print assertion failures to log
FORCE_ENABLE_DEBUGCONFIGURATION: Enable FAudio's debug functionality even in Release mode
XNASONG: This is just a feature I have for FNA. You can turn this off if you feel like it.
To change the build type (Debug/Release) and the above options,
ccmake is the easiest route:
mkdir flibitBuild cd flibitBuild cmake .. ccmake ..
This will let you toggle the options as you see fit, and CMake will regenerate the build files accordingly.
My recommended build configuration for Proton debugging is this:
mkdir flibitBuild cd flibitBuild cmake .. -DXNASONG=OFF -DFFMPEG=ON -DCMAKE_BUILD_TYPE=Debug
Part 4: Debugging FAudio at runtime
For the most part, the best weapon you have is PROTON_LOG=1. If you have a debug build of FAudio, you have access to assertions, which will tell you most of the obvious errors (unless the program has a bug of its own... looking at you, guy who wrote Skyrim's X3DAudio code) in the form of a graphical error window.
The other thing a debug build will give you is full DebugConfiguration access, which can be enabled with environment variables:
# Do not actually do this! PROTON_LOG=1 FAUDIO_LOG_EVERYTHING=1 %command%
FAUDIO_LOG_EVERYTHING part? Don't do that. Really, really don't do that. Instead, consider these:
FAUDIO_LOG_ERRORS # Prints really bad errors. Get ready to crash! FAUDIO_LOG_WARNINGS # Prints questionable behavior. Get ready to probably crash? FAUDIO_LOG_INFO # Prints lots of data that is hopefully normal and not weird FAUDIO_LOG_API_CALLS # Prints every API enter/exit. Hope you have a big hard drive! FAUDIO_LOG_FUNC_CALLS # Prints every internal function enter/exit. See above! FAUDIO_LOG_LOCKS # Prints every mutex lock/unlock. Yup, you guessed it, see above. FAUDIO_LOG_LOGTHREADID # Thread pointer will be printed with each message FAUDIO_LOG_LOGFILELINE # Source filename + line will be printed with each message FAUDIO_LOG_LOGFUNCTIONNAME # What you'd expect.
Depending on the situation, combinations of these can produce extremely helpful logs that sometimes directly point at the problem!