-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wwise integration #1
Draft
bh247484
wants to merge
19
commits into
main
Choose a base branch
from
wwise-integration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What is it?
A novel Wwise integration with id Software's Quake III (1999) inspired and informed by this presentation by Robin Fencott. The Quake source used here is forked from ioquake3 which is itself a community maintained fork of the publicly available Quake III source code.
This project contains original music, sound design, and new interoperable code that integrates Wwise's modern C++ api and Quake III's nearly 25 year old game engine written in C.
Below I've written a short account of the process. It's also worth browsing this PR's diff. Much of the code is self explanatory.
What does it look and sound like?
quake-int-clip.mp4
Attn: Be sure to unmute the above video. Github mutes embeds by default.
Original Sounds
With the exception of some environmental level ambience and voice over cues, I disabled all Quake music/sfx and replaced them with the following original sounds.
All the audio assets can be found in this Google Drive folder. Give the full theme a listen if you'd like. Only a portion of it appears in the video above.
How did you do it?
Interop Challenges
The highest hurdle by far was project configuration. Luckily ioquake3 has a sane and reliable VS 2019 solution prerolled. A good place to start. From there I added a new Visual Studio project and configured it to build with Wwise's sdk dependencies. Then I created a Wwise wrapper (header, cpp) which made C++ code callable from extern "C" defined functions.
Initially I tried building and linking this code to the quake3 project statically. I was assailed by linker errors. After a largely fruitless struggle I switched tactics and tried linking my code dynamically. That worked for reasons I can't fully explain. My guess is that there were fundamental incompatibilities linking C++ code through the C compiler (vice versa probably would've been fine) and precompiling my C++ into a dll allowed me to sidestep those incompatibilities entirely. The C compiler was able to link into the dll binary soup without concerning itself with the soup's recipe/preparation.
I think static libs require some more involved linking during the build process since they're linked at compile time, not run time. Pure speculation though. Like I say, can't fully explain.
Quake Engine
The next task was a little forensic paleontology on the Quake engine code. To the original devs credit it's a surprisingly traversable and intuitively patterned code base. I began by forwarding some sfx ids to my C++ code (and logging the values) to prove out my theory of interoperability. Arbitrary (i.e. meaningless) integer ids made the sounds difficult to differentiate so later on I had to chase down the pre-hashed sfx name for debugging as well.
Finally I needed to identify three key sites in the game engine's lifecycle where I could trigger three reciprocal Wwise methods.
After some digging I found I was able to hook into a few lifecycle functions (
S_Init()
,S_Update()
, andS_Shutdown()
) defined in quake's sound engine.Finalizing Integration
Finally I needed to build out Wwise events/sfx and generate some soundbanks in the Wwise authoring tool and trigger those sounds with input from the Quake engine. I began with a simple test event/sfx, generated a sound bank, and fired the Wwise event whenever any forwarded sfx trigger arrived from the Quake engine. That sounded/looked something like this...
quake-clip-2.mp4
Attn: Be sure to unmute the above video. Github mutes embeds by default.
Note the use of the Wwise profiler's capture log in the video. Useful for debugging.
With that pattern established I simply created new Wwise events/sfx, mapped them to the sfx ids from the Quake engine, and tweaked sound design as needed.
What would you do differently?
The project is inherently hacky but there's still housekeeping/organization optimizations that could be made. In particular the directory hierarchy doesn't make a lot of sense.
The original ioquake3 repo separates VS project files from their associated source files and uses a build folder for debugging/release output. I didn't follow that pattern which allowed me to group my code sensibly and centrally but it makes less sense in the context of the code base at large. Also I used absolute file paths specific to my system for some linking/dependency inclusion so this project is not easily shareable.
There was a lot of throwing things at the wall to see what stuck (and compiled) before settling on the dll approach so the early part of the process was lawless cowboy coding. I spent some time cleaning up after myself but a fresh start with foreknowledge of best configuration practices would yield better results. Now that I've established this pattern I may find some other classic games with public C source code and give it another go.