Skip to content
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
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft

Wwise integration #1

wants to merge 19 commits into from

Conversation

bh247484
Copy link
Owner

@bh247484 bh247484 commented Jul 23, 2023

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.

  1. An original theme that loops while the game is played. Composed with Ableton Live, a Nord Stage 3, and an Elektron Syntakt drum machine. Prince fans will note the distinct kick drum pattern reminiscent of his immortal 1987 classic "Housequake."
  2. A UI sound that triggers when hovering over menu items. A sound is randomly selected from a group of 6 rhodes keyboard notes, all diatonically related to the theme music.
  3. Finally a custom kalimba/metallophone hybrid arpeggio is triggered when a (specific) weapon fires.

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.

  1. Somewhere to trigger Wwise sound engine initialization.
  2. Somewhere to trigger Wwise updates every "tick" interval of the gameloop.
  3. Somewhere to trigger Wwise sound engine termination and free allocated memory.

After some digging I found I was able to hook into a few lifecycle functions (S_Init(), S_Update(), and S_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.

@bh247484 bh247484 self-assigned this Jul 23, 2023
@bh247484 bh247484 marked this pull request as draft July 26, 2023 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant