Sound Channel Mixing in Games

Miscellaneous Forums/General Discussion/Sound Channel Mixing in Games

Anyone had any experience with mixing sound channels in games? What I mean is, say two enemies blow up at once. If you play two explosions it's too noisy so you decide OK, I'll just play one, fine. But what if the enemies blow up one slightly after the other. If you only have a single channel you have a choice of let the original sound continue playing or cut if off and play the new explosion (this normally sounds pretty bad, makes clicks etc). So if you have multiple channels and multiple explosions occuring at different times, it still gets too noisy.

Furthermore, say the user presses shoot at the exact frame that an explosion occurs and when both samples play at once, they mix and produce a distorted crackle because they are overloading the soundcard due to getting square wave forums at max volume (I think). Does anyone know what I mean? I can duplicate this very clearly by playing two sound effects I have at once.

Now, in a music program this can occur too, so you either find the correct volume levels for all channels where it doesn't happen or you bung on a Compressor DSP which looks to see when a sound is peaking and then reduces it to keep it all at max volume but not making flat peaks (don't know the technical term form this).

So anyway, seeing as BMax or BPlus doesn't have a built in compressor, I'll have to try some kind of dynamic volume balancing. What I'm thinking is when the 2nd sample plays, play it at 50% vol and reduce the original one to 50% as well. Would this mean the total is 100% or doesn't it work like that? In fact would it sound funny having a sample suddenly half volume? Likewise 3 samples = 33% each and so on. I just worried that say 10 samples = 10% each and it could sound crap. Really for most samples you only want to reduce the first bit which is loudest, like a snare drum with reverb or something, and then you could boost the level back up for the last bit which is quieter, but how to do that I've no idea. It would have to be pretty low level unless I made a volume ramp for each sample that get's applied each frame based on delta timing or something...

Anyway thought I'd bandy this idea around and see what people have to say :-)

[edit] please test this (pressing 3 is noisy and crap (distorted/crackly) on my PC):

http://www.greyaliengames.com/misc/soundtest.zip (587kb)

Press keys 1-4. 1=A, 2=B, 3=A+B(100% vol each), 4=A+B(50% vol each). Esc = Exit

here's the code:
Strict
Global a:TSound = LoadSound("match.wav")
Global b:TSound = LoadSound("land.wav")

Global c:TChannel = AllocChannel()
Global d:TChannel = AllocChannel()

Graphics 640,480,0

While Not KeyHit(Key_ESCAPE)
	If KeyHit(KEY_1) Then PlayA(1)
	If KeyHit(KEY_2) Then PlayB(1)
	If KeyHit(KEY_3) Then	
		PlayA(1)
		PlayB(1)
	EndIf
	If KeyHit(KEY_4) Then
		PlayA(0.5)
		PlayB(0.5)
	EndIf
Wend

Function PlayA(vol#)
	a.Cue(c)
	c.SetVolume(vol)
	c.SetPaused(0)
End Function

Function PlayB(vol#)
	b.Cue(d)
	d.SetVolume(vol)
	d.SetPaused(0)
End Function


I can't say I've ever noticed this problem.

If it was a problem of baddies being killed at once I might just put them into a 'dying' state and every [small interval] explode one baddie that's in the dying state. So the explosions would be staggered a bit. This might look nicer visually as well and shouldn't have any gameplay impact.

Maybe it's just the samples I'm using or my soundcard or amplifier? They are quite loud but don't have flat peaks. Perhaps I should upload a demo so people can hear the sort of thing I mean. I'm amazed you've never noticed this John with your long list of games.

As for the code solution, I hear you, but in my case the baddies are gems and you need to blow them up in the same frame to clear the way for new ones, so I can't really delay them.

I've just implemnted some basic channel balancing as per my suggestion above and including monitoring the channels every frame so I can boost the voume of each up again when one finishes playing. It seems OK actually. Certainly no nasty noises, but when many play at once it does seem a tad mute. Perhaps the answer is not to completely balance, but have a max peak like 150% and work up to that, or to play the newest sound the loudest and fade the old ones more (or vice versa!). The experiment continues...

I posted a test app and code at the top now.


Anyway thought I'd bandy this idea around and see what people have to say :-)



I tend towards the other solution - have a few channels for specific things (ie explosions, laser fire etc) and have new entrants override the old... I don't see why that should generate clicks. No channel operates at full volume and neither does any background music, so there's no distortion either.

Part of that decision is based on not wanting to continually process audio volume, but with Max being faster than B3D you may feel you have the time; Partially it is also based on being wary of continually filling the player's ears with 100% vol... That’s not going to be particularly dynamic and could wind up unremitting and tiring to listen to.

Thanks for your input. Clicks occur when a new sample starts playing and the old one hasn't finished, the jump in the sample value seems to make a click in Max and Plus. But admittedly these are samples played at full volume.

Did you try my example with the distorted sound?

***
Please can someone test my demo above (download it) and see if the sound is distorted on their PC. Thanks.
***
Meanwhile I've maed an array of channels that autobalances when you play a new sound. This means some sounds get reduced in volume when new ones play, you sometimes notice but it's not obvious. I tried boost the volume back up when channels finish playing but it sounds odd when a vol is boosted up on longer sounds so I left this out in the end.

A hard choice is deciding how many channels to have as the more means the lower volume each could in theory be played at e.g. 10 channels = 10% each which is a bit rubbish.

Also in the end I made it so that if a channel is already playing, it won't be hijacked to play the new sound, only channels that are not currently playing will be used (athough this is optioanl). Obviously this can mean that if all channels are in use, the sound doesn't play at all which may not be 100% desirable, so I'm looking at a way to make sure that certain sounds ALWAYS get played even if worst case another channel get's hijacked, OR a temporary channel get's made and then destroyed when it's finished playing.

I've also made "reserved" channels in the array. These ones are special and won't let any old sound play on them, just the specified ones. This means you can avoid having multiple instances of the same sound playing across the channels if you want to control a sound to only play when the previous instance has finished.

Phew typing that up was good as I got some new ideas :-)

One thing you can do is have EQ zones. Take a 24 band EQ, divide the thing into say 4, and make 6 samples each with different EQ bands audible.

Sample 1 would use EQ bands 1,6,12,18
Sample 2 would use EQ bands 2,7,13,19
Sample 3 would use EQ bands 3,8,14,20
Sample 4 would use EQ bands 4,9,15,21
Sample 5 would use EQ bands 5,10,16,22

If you do this, all the explosions will sound generally the same (not exactly thought)... you alternate the explosion samples, and since the explosions are using totally different frequences, they don't pile on each other quite as much.

I don't know if they do this much in video games, but in movies you will notice that voice, sound effects, and soundtrack music are all EQed to fall into different frequency bands more or less... they did't do this in a lot of older lower budget productions, which is why sometimes you watch old B horror flicks and it is impossible to hear what people are saying.

Easy fix. Little pitch random for each explosion. and ofcourse you cant have full volume on every channel. That will sound great when one channel playing but will smash to the roof because there are no headroom playing "many" channels. Try to be dynamic on the channel mixing.

Easier fix. Don't worry about it.

@Grey

Your test works fine for me, in all cases.

SB Audigy, WinXP Pro SP2

I'll try it on my notebook computer later...

EDIT: Yep, fine on my notebook too: onboard sound, WinXp Pro SP2.

RexRhino: Interesting idea thanks, quite a lot of work though tweaking the samples :-(
Others: thanks for your input
Impixi: Thanks for testing. So when you press 3 it sounds louder but not distorted on your setup? I have an SB Audigy2, maybe it's burnt out or somthing...

Sounds absolutely fine on my Audigy 1.

Audigy 1. Latest drivers (I think).

3 sounds louder, no distortion.

hmm, OK, I definitely get a small distortion but the distortion is more obvious on my headphones than my main speakers. Same amp, different output.

Test works fine here. I think you're worrying about this 'issue' too much, Grey. :)

yeah and I've gone and spent ages making a TChannelArray that mixes sounds etc, sigh.

there *is* distortion, and there has been on all four of the PC's that i tested on. The problem also makes sense if you think about it too.

the phases of the two sounds mix. two sounds at full + phase will push the sound card over it's digital limit (like pushing an INt over it's highest value....) Clever drivers/cards do analogue distortion which means if int>max then int=max. :)

Thanks for confiming this dude, I knew it was there.

Haven't had time to try your code, will give it a go later - However just as a point of note on a different app I have been developing on my laptop I have distortion (at times) when trying to play one sound as click events happen over buttons - this doesn't occur on my main PC - which may suggest it's platform specific issue. Will try your code later on Both my laptop and main PC and let you know the results - Regards - just tested on my main PC, the results were:

3 - may be slightly 'overdriving' a sound card - 4 - sounds less 'punchy'. Have you tried digitizing some speech and using this as sound files a and b ? May give you a clearer indication as to the level of distortion you are receiving.

@Cygnus - sounds good...

Thanks Blitzplotter. Yeah 3 plays both a full volume so it sounds overdriven/distorted. 4 is both at 50% volume making a total of 100% vol so should be OK.

Just thought, my laptop's sound drivers are goosed and cause distortion / break-up anyhow - another of those jobs that hasn't made it to my top10 of things to do... sorry.