Thread: RE: [GD-General] Writing an audio mixer
Brought to you by:
vexxed72
From: Brian H. <bri...@py...> - 2002-03-15 22:28:34
|
> Have you considered looking at the SDL? www.libsdl.org - it > works on Mac, Linux, Windows and a number of other platforms. I'm familiar with it, given that we use it for our MacOS, BeOS and Linux games =) I avoided it early on because it was faster for me to just write up my own stuff (where I controlled the abstractions) instead of becoming dependent on a third party. If I had to do it all over again I may have gone 100% SDL though. > Another candidate could be "OpenAL" - www.openal.org. I have no aversion to using open source software -- we use Ogg Vorbis, Lua, Zlib, and IJG (JPG)-- but I try to do so only when there's a very compelling reason to do so. Integrating OpenAL or SDL into our main source trunk will probably take longer than just writing an audio mixer. Brian |
From: Brian S. <bs...@mi...> - 2002-03-18 19:29:52
|
Threaded is easier than non-threaded? Ha! No, I think the advantage is that a non-threaded architecture is more = portable (as Brian Hook has already mentioned, old Mac OS doesn't have = preemptive threading, and older consoles didn't either) and it's more = efficient not to have a separate thread if you can run your main loop = fast enough to service the sound buffers. Threaded is easier if you're a company like RAD selling a sound engine, = because you can guarantee good performance and you don't have to field a = bunch of calls from people with games running at 15 fps complaining that = their sound is dropping out. As for SMP, well, about 0.00001% of gamers are going to have 2 or more = processors ;) --brian -----Original Message----- From: Mads Bondo Dydensborg [mailto:ma...@ch...]=20 Sent: Saturday, March 16, 2002 2:39 AM To: Ignacio Casta=F1o Cc: gam...@li... Subject: Re: [GD-General] Writing an audio mixer On Sat, 16 Mar 2002, Ignacio Casta=F1o wrote: > Hi, > I will be writting sound mixer next week, and I have to admit that I=20 > have no idea of sound programming. I could use sdl or any other=20 > library, but i just want to do that myself to learn how it's done.=20 > I've been looking for info about sound programming witout much look,=20 > I've only found low level details about the sound blaster :-( So if=20 > somebody knows where to find a good tutorial about this, I would=20 > really appreciate it. I do not know about tutorials, but I wrote my own mixer once in about = 1000 lines of code. It used a seperate thread, because I thought that to = be easier. The problem with my code was that I could only support mone 8 = bit samples. This is easy to do. When you want to support stereo, or = even more channels, and formats where the byte order is important (e.g. = 16 bit samples), it begins to suck. Also, you need to support a number = of different interfaces if you wish your code to work across platforms. > Anyway, I just can learn that by reading source code, for example,=20 > quake's sound engine runs on every game update, while sdl's and=20 > minifmod's run in a different thread. Updating the audio in the game=20 > loop seems to be easier to me, at least i have to write less platform=20 > independant code, but it seems that you have that work already done.=20 > On the other hand threaded audio seems to be the right thing, since=20 > most libraries do that. Threaded is easier. For _ultimate_ performance, you want to schedule = yourself, in this case from the game loop. But, seriously, who needs that? Carmack might, because he writes to = highend metal, but the rest of us? You loose SMP benefits, etc. YMMV. Mads --=20 Mads Bondo Dydensborg. = ma...@ch... I disapprove of what you say, but I will defend to the death your right = to say it. - Beatrice Hall [pseudonym: S.G. Tallentyre], 1907 (many times = wrongfully attributed to Voltaire) _______________________________________________ Gamedevlists-general mailing list = Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-general Archives: http://sourceforge.net/mailarchive/forum.php?forum_idU7 |
From: Brian H. <bri...@py...> - 2002-03-18 19:43:31
|
> Threaded is easier than non-threaded? Ha! Well, I think threading is _conceptually_ easier than non-threaded. Having a thread that basically just sits there waiting to feed a stream is much cleaner than remembering to sprinkle your code with "updateAudio()" threads. Of course, if you don't know how to deal with portability issues and threads, or if you've never dealt with synchronization problems, yeah, then _in practice_ threading is WAY uglier. Brian |
From: Tom H. <to...@3d...> - 2002-03-19 00:28:19
|
At 04:00 PM 3/18/2002, Brian Hook wrote: >One other thing that hasn't been mentioned is latency. With a threaded >audio mixer you can get pretty low latencies since you know you'll be >serviced at fairly regular intervals. With a synchronous mixer, you >have to trade off robustness (underflows) for response time. For a >puzzle game this probably isn't that big a deal, but it's something to >be aware of. Setting up a one second buffer gives you a lot of lee way >on servicing the stream, but you've now established a pretty big ass >delay in your audio stream. Lets assume that my frame rate should never drop below 20fps. This means my sound buffer must be at least 50ms if I'm going to service it once per frame (two 50ms buffers for double buffering). This also means that I have a 50ms latency for kicking off new sound effects. If the frame rate drops below 20fps then I'm going to have ugly problems (skipping on MacOS, repeating on Win32). I think you can stretch this out to 70, 80, etc ms ... though I'm not sure where exactly it starts to feel disconnected from the action. The other option is to go with a threaded system. However, for systems without threads, or systems like MacOS where you only have cooperative threads (icky kaka) you end up right back at the once per frame thing or dealing with doing your buffer filling in response to interrupts. Basically, if you can get away with saying the frame rate will never drop below some number (which is strictly a sound effect latency problem), then you can deal with updating the sound buffers once per frame. If you can't, then you either need to sprinkle multiple sound updates through the code or go to a threaded / interrupt based system. ------ I think if I was to set up a mixer, I would push the issue of how to service the hardware down to the system level. I would stack up play commands from the game side and generate the mixed results in response to a function call: GetMixedData(int iBytes, void* pBuffer); which would give you the next iBytes worth of mixed sound data into pBuffer. This function would need to be interrupt and thread safe. Then you just call this function from where ever you update the sound hardware for that system. The mixing code is all cross-plat and you only have to write up a page or two of code for stuffing a system buffer with audio (just like Ogg Vorbis). The buffer sizes are all system dependant, and can even be varied at run time if you like. Tom |
From: Tom H. <to...@3d...> - 2002-03-19 04:46:00
|
At 04:41 PM 3/18/2002, Brian Hook wrote: >Steady state frame rate situations are easy to support, it's when you >have things like loading screens and long idle periods that you get >hosed. For example, say you have background music playing and you now >load a map file that's 3MB. You probably can't pull that up in < 50ms. Yup ... Long file I/O kills that kind of sound system. It's often ok to shut off background music during long IO though. >To combat that you end up sprinkling "updateMixer()" calls everywhere >you _think_ you might have a long delay. This becomes error prone and >tedious. Yes .. I'd do everything I could to avoid such a thing. >The problem is that the mixer code can get very, very slow, depending on >how much optimization work you want to put into it. Panning, volume, >handling repeating sounds, etc. add up to a lot of overhead, especially >on lower end systems. Unless you're doing the mixing on another CPU or are running into situations where you're taking up double interrupt hits (something that can happen on the Mac and make things slower than they should be .. not 100% clear on this one myself), it doesn't really matter when/where you do the work. It's still going to take the same amount of time. Unless I'm missing something, I don't really see how this is relevant. >Actually, you'd need to write that function differently depending on >whether it was interrupt driven or not, since thread sync works >differently than interrupt sync. In all likelihood the right way to do >it would be write a portable function that had a system specific >synchronization wrapper around it. Yeah ... somethin like that ;) Tom |
From: Brian H. <bri...@py...> - 2002-03-19 00:00:25
|
One other thing that hasn't been mentioned is latency. With a threaded audio mixer you can get pretty low latencies since you know you'll be serviced at fairly regular intervals. With a synchronous mixer, you have to trade off robustness (underflows) for response time. For a puzzle game this probably isn't that big a deal, but it's something to be aware of. Setting up a one second buffer gives you a lot of lee way on servicing the stream, but you've now established a pretty big ass delay in your audio stream. Brian |
From: Brian H. <bri...@py...> - 2002-03-19 00:06:04
|
Doh, sorry, latency was mentioned by Mickael Pointier. Sorry for any confusion. > One other thing that hasn't been mentioned is latency. |
From: Brian H. <bri...@py...> - 2002-03-19 00:41:41
|
> Lets assume that my frame rate should never drop below 20fps. Steady state frame rate situations are easy to support, it's when you have things like loading screens and long idle periods that you get hosed. For example, say you have background music playing and you now load a map file that's 3MB. You probably can't pull that up in < 50ms. To combat that you end up sprinkling "updateMixer()" calls everywhere you _think_ you might have a long delay. This becomes error prone and tedious. > The other option is to go with a threaded system. This is conceptually much cleaner, but if supporting a console or MacOS is important, then you may be out of luck with this direction. > I think if I was to set up a mixer, I would push the issue of how to > service the hardware down to the system level. I would stack up play > commands from the game side and generate the mixed results in > response to a function call: Yep. That's pretty much the standard way of doing it. The problem is that the mixer code can get very, very slow, depending on how much optimization work you want to put into it. Panning, volume, handling repeating sounds, etc. add up to a lot of overhead, especially on lower end systems. > This function would need to be interrupt and thread safe. Actually, you'd need to write that function differently depending on whether it was interrupt driven or not, since thread sync works differently than interrupt sync. In all likelihood the right way to do it would be write a portable function that had a system specific synchronization wrapper around it. Brian |