...implementing a 3rd party sound engine. Trust me, it isn't. And yes, it is a pun. I've looked it up and everything.
Playing audio in Lode Runner seemed like an easy thing to do and initially, it was. I started off using XNA's media class to get sound playing to help motivate me while I developed. Using SoundEffect and SoundEffectInstance for sound effects was easy and worked flawlessly.
The music tracks was a little tricker since loading audio from streams or without the Content Pipeline isn't supported. This could have been avoided if all the tracks were distributed as individual files but I wanted to stay true to the original Presage resources and package them into a Presage resource file (*.PRS).
I would have used irrKlang since I've used it in a previous project and found it very simple and easy to use but unfortunately, the .NET version is not actually Mono compatible (irrKlang is cross-platform but doesn't support mixed mode assemblies) so I went looking for an alternative.
IrrKlang is quite good. Like I said, my Previous project used it, a game called Captain Yates: The Freedom Quest! which was a cross between Lode Runner 2 and Command Keen. I still want to finish it one day. My most recent work was to recreate the game from scratch in Unity (from Truevision3D), focusing mainly on movement, doors and teleports.
Captain Yates: The Freedom Quest!
Criteria for a sound engine
- Cross platform support; Windows, Linux and Mac
- .Net/Mono compatible wrapper available to save time
- Quick to implement; with two people working around normal jobs, time is important
- Support for file streaming for the music tracks
- Out of the box support - no plugins or extending if necessary
- Not cost a fortune (read: free)
I found the following options:
irrKlang
Despite being afforable it doesn't work with the Mono Framework. This means no Linux or Mac support. The reason is irrKlang is a mixed mode assembly but Mono Framework doesn't support mixed mode assemblies. Until Ambiera changes this, irrKlang is quite useless for .NET cross platform development.
FMOD
Whilst it does match the criteria, their ".NET wrapper" - three C# classes that simply calls their library using marshalling - isn't really something I want to use.
I went no further with FMOD. No tutorials or help files and virtually no documentation - if you aren't fluent in C++ and aren't using CryEngine, don't bother with FMOD.
Bass
After irrKlang and FMOD I tried Bass. Bass is easy to add to any .NET programme. The main problem with Bass is I can't for the life of me get it to work on Mac OS X with Mono and I got no real support from the developers.
NVorbis
Next, I tried a NVorbis wrapper by Nick Gravelyn. This wrapper allows you to stream Ogg Vorbis audio files with XNA/MonoGame.
To support streaming from Presage resource files, I added a small mod to BufferedReadStream.cs. After doing this, I soon found numerous issues with NVorbis attempting to read data well past the end of a stream when decoding audio. To makes sure it wasn't me, I used Nick's original code + NVorbis original code and sure enough: the same issue.
To this day and countless wasted hours later, I still haven't found out why this happens, and to be frank, I simply no longer care. If it takes me a week to get nowhere with all the documentation in front of me then, arrogant or not, the fault is not mine. My temper is well fired up by this point which means it is time to try another approach.
OggSharp
A long dead project, where most of the code originated from this port, was the answer. After numerous attempts, the project cannot be converted to VB without a deeper understanding of C# than I have and/or understanding of the Ogg audio format. The solution is to create a C# library and access it from VB that way.
Streaming is done by reading samples and submititng them to the buffer of a DynamicSoundEffectInstance.
This method works really well on both Windows and Mac and doesn't need any of the Vorbis libraries. The only downside is it doesn't always play a song when it is supposed too and since this only happens when running outside of Visual Studio, it is a little hard to track down.
You can download the modified source + a class to stream Ogg audio which works with XNA and FNA. MonoGame will need a DynamicSoundEffectInstance added in order to work.
Summary
I never thought adding music would be so hard. I've been haunted by this now on and off for a year. Far too much time has been wasted that I'm not at all happy with. Finally though, all audio is now working across both Windows and Mac and I'm rather happy it is all sorted.
Sound effects = FNA's SoundEffect and SoundEffectInstance
I had to resample all the original audio files because as it turns out, Open AL is not as good as DirectX at playing raw audio. This wasn't ideal but I can't really do much about it.
Music tracks = FNA's Song and MediaPlayer
The music is taken care of with FNA's Song and MediaPlayer classes + the Ogg/Vorbis libraries. I had to make small additions to both of these to support streaming audio from Presage resource files.