🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

A good reason not to use SDL_mixer

Started by
2 comments, last by Kylotan 18 years, 9 months ago
One of the musicians on my team recently brought something to our attention, claiming that SDL_mixer would *not* be a good audio API for us to use (we've been using it since the beginning of our project). Allow me to paraphrase what he said:
Quote: >>>PROBLEM<<< Looping in SDL_Mixer is a native feature with a nice big ol' skip whenever you loop... which is JUST NO GOOD!!! SDL_Mixer makes use (to my understanding) of a ring buffer. However, looping does not utilize a ring buffer, so at the point of looping, there is latency as such that the song ends, gets unloaded from memory, and then gets reloaded at the begining. >>>MOTIVATION<<< I recall "LIM" of #SDL (Sam Lantiga - the author of SDL_mixer) on freenode stating that SDL_Mixer is, by and large, a hack and a toy, and that one would be better off making their own mixer built on SDL_Sound. But that's an entirely different can of worms. Quote by LIM: "Looping only sections of songs may be a little more tricky to do (do you think this type of functionality will be necessary Joe?), but I think it's possible." VERY NECESSARY! Just as important as being able to loop or play .ogg files at all. I've designed (and I'm pretty sure Rain has too) all songs to be looped from a certain point. The only way you can adequatly do looping with a break is to plan on an ending of the song... like putting a cd in your player, and looping just the one track (e.g. castlevania- symphony of the night or lament of innocence, or command and conquer (any part of the series)). Otherwise you're dealing with a model like this (with or without intro) Intro-----section A----------Section B---------section A-------- | * * | start percieved begining (pb) loop Note that the loop is not at the resubmission of the perceived begining (when you think the song actually loops), but much later. This is because of echo, delay, reverb, and general decay of instruments that carry over from the B section to the A section. There comes a point when the second section A is identical to the first... but that happens much later. If we just made the song the exact length of the two perceived beginings, the listener would hear a disjunct pop or studder or at best... an uneasyness. This is due to the fact that the waveform wouldn't align up, and doesn't even take into account latency of reloading the file in and out of the heap without the proper use of a ring buffer. >>>SOLUTION (1)<<< So what's the solution? We, as composers, write out the song until the second perceived begining. From there, we just cut and paste a new A section, and record that... noting the sample point (it's very easy to calculate if you fix your frequency rate and use a uniform bit depth for your wav file). In soundforge for sure, you can use wav or aiff markers, and then plug them into the .ogg tag which is in turn read by SDL_Mixer. SDL_mixer then transparently loops the file from Begin_point marker to Loop_point marker. It's only a matter of balancing the buffer size with the computer speed at that point, and as far as the programer is concerned, SDL_Mixer takes care of everything, so the problem (if any) is encapsulated. >>>SOLUTION (2)<<< Many months ago I was talking to LIM in #SDL on freenode, and he advised that you do it all in SDL_Sound (more tested, faster, more stable, less resources). Being that I'm a craptacular programer, I didn't follow his advice, and instead found a workaround on the web. Basically, you modify the sdl_mixer.dll, and use vorbis for audio format, and you're set. It's a minor hack that adds support for "START" and "END" markers in songs. So then you put it to the composer to find out the exact sample where they want their song looped, and you loop it. In the C++, the code does not change. You just use SDL_Mixer to play audio with looping (keep it infinite), and use play and stop as normal. The loop points are stored in the tag on the .ogg file itself, so nothing has to be kept elsewhere in the game scripts. Basically it's like the good ol days when you could tell Midi files to loop, and they would. Only difference now is that they will be pretty clean audio files that loop seamlessly (it perpetuates the ring off the loop point, rather than having to chunk the file always from the begining). There is, of course a catch. Now all audio must be looped. But there is a workaround for this too! 9/10 times in a game, you want the music to be looped anyway, except for stuff where you want the music to just go to silence (game over perhaps?). Instead, just do a timer event, and after a certain point in time, kill the music. And if we're worried about latency, we can add a few seconds of silence to the end of the particular track. Easy, yes? I think it's much MUCH easier than writing our own mixer, but if you wanna go that route... I could work on something in my spare time (what am I saying... I haven't had time to write music, let alone code!).
Of course, the third solution is to simply use another audio API, and I'm starting to look into OpenAL as a favorable alternative (though I still need to read the documentaion). Has anyone else come across this issue when they decided to use SDL_mixer and, if so, how did you solve it? Both of my composers are seeing this as a very serious issue and places a barrier on the music they can create. So I wanted others to be aware of it and see what people had to say about the use of SDL_mixer.

Hero of Allacrost - A free, open-source 2D RPG in development.
Latest release June, 2015 - GameDev annoucement

Advertisement
I got the skip during loop to quit by cutting off the gap in the beginning and end of the loop in audacity, then encoded them to ogg cause for some reason mp3's like to skip.
I just use SDL_mixer to play midi files and OpenAL for everything else. *shrug*

Good information though..
The answer is to use a second buffer so that you can swap from one to the other instantly. Graphics programmers have known this for years... Maybe SDL_Mixer isn't obviously suited to this since you only have 1 music channel, but I expect that can be hacked around. In fact, if they just changed it to 2 music channels then you can do pretty much everything with it.

As for the 'solutions'... isn't solution 1 obvious, regardless of your API? If the decay of instruments at the end of a section is an issue, then you really need to overlap that ending with the beginning of the next repetition, which means you're wanting to do something which is beyond the usual definition of loop, and more like a crossfade (without the fade). It involves potentially streaming the same file twice at once, and from different positions, which is presumably why SDL_Mixer doesn't give you a way to do that.

This topic is closed to new replies.

Advertisement