Okay, where was I…
So I had a basic music player, which would decode Ogg Vorbis data using libvorbis and play it to the user with Cubeb. For the basic purpose of adding Ogg Vorbis support to a game that originally lacked it, this was good enough.
Or… so I thought. With the release of my Ogg Vorbis mod, I was no longer the only one testing clownaudio. Eventually, I received a bug report that it didn’t work on Windows XP.
Windows XP compatibility
Now I know some of you will roll your eyes at the thought of supporting such an outdated OS, but the nerd in me wasn’t content with making a mod that was less portable than the game it was based on. Besides, it’s just a glorified music player – why couldn’t it work on Windows XP?
Well, it turned out that the problem was Cubeb: unlike SDL2, it only supports Windows Vista(?) and above. Great. I’d spent all this time migrating clownaudio from SDL2 to Cubeb, only to find that it ruined backwards-compatibility.
That said, I didn’t want to just rip out my Cubeb code and plug the old SDL2 code back in. No… SDL2 is big and bloated and old and gross, while Cubeb is new and shiny and cool. So, I decided to just support both:
To achieve this, I refactored clownaudio so that the Cubeb code was entirely decoupled from the rest of the engine, allowing it to be kept in its own source file. I could then create another source file that exposes the same API as the Cubeb one, except it implements it using SDL2 instead. Then, at compile-time, I could simply choose which ‘backend’ I want, and the produced DLL would use the appropriate library for audio playback. That way I didn’t have to give up Windows XP compatibility or using a cool new library.
And so my mod started to provide two DLLs: an SDL2 one for Windows XP, and a Cubeb one for everything else.
I’d say this is where this particular story ends, but it isn’t:
The third option
I never quite got over the fact that I had to choose between bloat and non-portability: using SDL2 produced a DLL that was over a megabyte large, which is absolutely absurd when all I needed was something to ferry audio samples to the OS.
I thought that maybe I should ditch SDL2 and Cubeb, and just create a new backend that uses DirectSound – the very audio API that Cave Story itself uses. That would be very minimal (incurring next to no DLL bloat as DirectSound is a system library) and it would be guaranteed to support any platform that Cave Story runs on.
However, I could never figure out how to use DirectSound: it wasn’t as easy as a callback function asking for samples every now and again – instead it looked like you had to do some crazy low-level stuff involving filling an audio buffer with data as it was being played. In hindsight, it was just your usual push-API double-buffer stuff, but back then it was just gobbledygook to me.
So I began to look around for a DirectSound wrapper library – something small that would provide a nice simple API for steaming audio. It was while looking for this that I found what would become one of my favourite libraries, even today:
I’d found a curious little library called ‘mini_al’, and it claimed to be exactly what I was looking for: a small library that provided an API meant for streaming audio using DirectSound. Except it wasn’t just DirectSound: it supported WASAPI, WinMM, OpenSL, ALSA, PulseAudio, JACK, CoreAudio, and so on; it supported everything.
But this is bloat, right? All I needed was DirectSound. Well that’s the amazing thing: this library is the exact opposite of bloat. Don’t want WASAPI or WinMM code wasting space in your executable? You can just get rid of it!
What I’d found was a single-header-file library – a library that prioritises portability, ease of integration, and minimising bloat. Unlike typical libraries, these ones aren’t compiled on their own and installed to your system as an unmodifiable binary; rather, these ones are compiled straight into your program from source. Because of this, these libraries often allow users to disable code they don’t need with nothing more than a
With this, I didn’t have to sacrifice portability or efficiency: I could have both:
And so clownaudio gained a third backend. I could have discarded the other two, but I liked the idea of maintaining a small collection of backends, even if one of them completed trumped the others.
To this day, mini_al (or ‘miniaudio’, as it’s now called) remains clownaudio’s preferred playback backend.
Honestly, I was hoping to cover more in this part, but somehow writing about this one subject has already taken a couple of hours. In the next part, I’ll cover the first step in clownaudio’s transition from a component in a Cave Story mod to a standalone audio library.
5 thoughts on “The tale of clownaudio – Part 3”
i have serious problem playing your “hyper & super sonic in sonic 1” hack
when i reboot on sega cd mode to get knuckles chaotix music ….. so the rom plays but no sonic sprite appear on the screen
i using Kega Fusion 3.64 with all Sega CD / 32x / genesis bios running ok
i am using geforce 210 …i am also tested on other computer and i got the same problem
was made ok
look the video:
the reboot was made at 30 seconds of the video
can you fix that ? please
sorry i can post on sonic retro forum
It’s a bug in Kega Fusion: when the Sega CD mode is enabled, DMA transfers stop working. You can see this same issue in Sonic 2 if you enable Sega CD mode while playing it. I’d recommend using another emulator instead.
question: gens emulator will works or not ?
this have genesis roms and sega cd support
but i don´t how make segacd mode reboot while genesis rom still works like as fusion does
oh i see your reply on other place sorry
how to do the segacd reboot on genesis plus gx ?
genesis plus gx will run on xp ?
some plan to add spin dash on this hack ? will be very cool i think