Writing more

This commit is contained in:
2024-09-04 13:04:38 -05:00
parent 778a110154
commit ecb078df71

86
pulse.txt Normal file
View File

@@ -0,0 +1,86 @@
Integrating Audio Into Our Game Engine
Chapter 1. Scoping the project.
So. We're making a game engine. Cool, yes, but our gimmick is that we're doing
it from scratch. As much as possible. We've made some progress:
[ ] Window Management
[ ] Input
[ ] 2D/3D Graphics
[ ] Menu Building
[ ] Supporting Tools (Math, Logging, Test Suite, etc)
Up next, we needed sound support. It needed to use minimal external dependencies, no libraries from github allowed,
must support at least Linux and Windows. Preferably support sound synthesis, mixing, multi-channel, and eventually
positional audio.
As the most ambitious and insane member of the development team, I naturally took on the challenge, not knowing what
i'd just signed up for.
To break the task down into managable steps, we generally try to spin up a minimal integration demo, first on linux,
then windows, then we wrap it into an API that can be integrated as another component of our game engine.
Without further ado, I set out to get some sound playing on Linux.
The obvious choice for sound API for us was PulseAudio (Why? What alternatives are available, and how did we arrive
at PulseAudio. This was a major design decision after all).
Right away, I was given reason for concern. Official documentation was light, to say the least. There were two example
programs, but unfortunately, they were to demonstrate what is known as the "PulseAudio Simple API".
Oh? There's a simple API? That's awesome, maybe progress can be made here. Well, not so fast.
Sure enough, the simple API lets you create a sound channel, and even play back raw PCM sound data over the
PulseAudio Server.
(Add a chapter about decoding OGGvorbis into raw Pulse-Code-Modulated sound data. That is interesting.)
(Include code snippets from pacat-simple)
Well, that's pretty cool, but what's the catch?
Well, for one, the Simple API does not even support changing the volume. Yes, you read that correctly.
Not to mention, a real-time game engine needs threading support, ability to playback multiple sounds at once,
introspection into the sound system for debugging purposes would also be nice, among other things.
Our pacat_simple program lets us spin up a connection to the PulseAudio server and upload PCM data that gets played
through your speakers. But our toy program is already kneecapped due to lack of Simple API features.
So... Unfortunately, I must learn and utilize the higher-order APIs to achieve our goals.
As previously stated, the official documentation was very light. To their credit, there was at least a website with doxygen pages, so
I was not totally in the dark. However, in total honesty, I could not make sense of how to utilize it. What function do I call first?
In what context do I initialize this? What order do I perform these tasks in? How do I use this threaded_mainloop thing it keeps
referring to?
Well, I bet to myself I could find useful examples of PulseAudio API on github, stackoverflow, so on. (I haven't, at least not yet.)
Stepping back to look at the big picture, this is just one Sound Driver API, on one operating system. Wow, this is going to be a mess...
Chapter 2 - Designing the system.
The overall design for our Audio system is as follows:
* Sound class
* SFX class
* Music class
* Stream
* SoundSubsystem abstract class, which would be derived for each low-level sound API we intended to support.
* ReMixer / SoundService
The ReMixer layer will construct and return a pointer to the appropriate derived subsystem.
The user of the library should not have to be aware of implementation differences between differing operating systems and sound driver APIs.
Chapter 3 - Implementing the PulseAudio Subsystem.
It's been a couple weeks since I first began researching this task, and began writing this article. In that time, I managed to reverse-engineer the
source code of the 'pa_simple' API to gain a basic understanding of how to utilize the advanced API. Using the pieces of information I gathered, I was ready to
build the PulseAudio subsystem.
Chapter 4 - Stateful Playback & Mixing
The next set of problems to be solved were that in which, we would like to be able to play a sound, and at an arbitrary point later, be able to pause, resume, seek, or mix several sounds together.
Additionally, we had not completed pushing the sound-loop code to a separate thread.