Advertisement

OpenAL Virtual Channel Manager

Started by July 14, 2011 06:58 AM
0 comments, last by Ashaman73 13 years, 4 months ago
I'd love to use FMODex but the license fee is now a steep $3000 even for indie game licenses not $100 like it used to be.

Anyway I'm trying to bring over the functionality of the virtual channel management from FMODex. I tell a sound to play and it returns an instance of a wrapper object around an OpenAL sound source. This tracks the current time of the sound playing and all that.

Then there's an algorithm that selects the instances of playing sounds closest to the listener and only lets OpenAL sources for that play. The sounds that are far away are culled out. If too many sounds try to play that are close enough not to get culled out, the closest ones are selected. Also priority comes in to play some how to additionally select among those. For example, character speech should have higher priority than a gunshot. The speech should be selected to play in the place of a gunshot even if the gunshot is actually closer, I think... Also I think volume of a sound comes in to play somehow.

I'm trying to create a sound manager that does this selection of sources well and makes sounds not cut in and out noticeably. I also want to get this done quickly and not spend months upon months tweaking an algorithm. Does anyone have some tips on how to do this kind of thing right?

I'm also using EFX for DSP effects and there are things like echo. Does OpenAL consider a sound to only be stopped when the echo stops? Can I pause a source and pause the echo along with it, and once I resume the echo continues from the same place? I'm trying to make it so I can pause the game or save it and let sound effects that were currently playing resume once the game is unpaused or loaded.


Basically my current approach is I have my audio system object. It maintains a pool of sources with number AL_MAX_SOURCES or whatever that constant is. When I play a sound it returns an object that stores attributes about the sound source which has things like position and velocity and what EFX effects are attached to it, and then a bunch of other tiny little OpenAL attributes. The object tracks the current time of playing within the sound. There are additional functions to stop, pause, and unpause the sound. Then there are functions to update its position and velocity.

The Audio system object uses some algorithm based on distance and priority to select from these playing sounds which ones are actually audible. When a sound that is playing virtually is suddenly selected for playing nonvirtually, it tells OpenAL to set up the OpenAL sound source and start playing a bunch of stuff. And it tells the sound to start from the current playback position that was kept track of virtually. The sound just cuts in at the time that it is supposed to be playing. This shouldn't be too noticeable since the sounds that are farthest from the listener are the ones that cut in and out. The closest sounds are all loud and mix together so the player won't notice.

A sniper round fired 500 yards away will be overpowered by a shotgun blast that just happened next to the player's ear. The sniper round will play virtually while overpowered. The shotgun sound will be done after 2 seconds, and the loud echoing sniper blast will suddenly cut in and the player will be able to still hear the loud echoey sniper shot that just occured. It would probably be notiecable though as the shotgun sound effect levels off towards the end and the sniper shot sound suddenly cuts in. However with a maximum of 32 sources playable at the same time I think sounds cutting in and out won't be too much of an issue. I doubt there will ever really be cases where 32 sounds audible at the same time anyway since ambient noises and faraway sounds will be culled out completely due to the listener being outside their maximum audible radius. And if there do happen to be 32 simultaneous sounds playing, it will all just be a massive cacophony and the player won't notice 1 or two sounds cutting in every now and then.


What I'm not sure about though is how to write the algorithm that selects which sounds to actually play. Selecting sounds based purely on distance from the listener is simple enough but adding priority is useful so I can prioritize things like NPC speech over birds twittering in the background. I'm not sure what the equation is when priority is involved. In FMODex there was a function that returned the audibility of a sound at that moment. I can't find anything like this in OpenAL. I imagine I'd have to write some algorithm that determines this by analyzing the waveform data and based on the amplitude of the sound at that moment and the gain of the source and listener. It would be useful to know that a gunshot 5 feet away completely overpowers something like the sound of snapping fingers 2 feet away not prioritize the finger snapping over the gunshot.

What I'm not sure about though is how to write the algorithm that selects which sounds to actually play. Selecting sounds based purely on distance from the listener is simple enough but adding priority is useful so I can prioritize things like NPC speech over birds twittering in the background. I'm not sure what the equation is when priority is involved. In FMODex there was a function that returned the audibility of a sound at that moment. I can't find anything like this in OpenAL. I imagine I'd have to write some algorithm that determines this by analyzing the waveform data and based on the amplitude of the sound at that moment and the gain of the source and listener. It would be useful to know that a gunshot 5 feet away completely overpowers something like the sound of snapping fingers 2 feet away not prioritize the finger snapping over the gunshot.

Your wall of text has almost crushed me :wink:
To be honest, I would use a very simple and easily tweakable system. In games reallty is not the top priority. Making your game easy to design should be much more important. I.e. analysing the audo sample to calculate a priority automatically could be easily ending in shooting your own foot.

Think about the player observing two npcs who wisper(low amplitude) about an important game event. The designer wants, that the player is able to hear the complete conversation, on the other hand the engine sound of a nearby car kicks it out.

A simple priority system would be the following:

float calculateFinalPriority( float fixPriority, float distance, float maxDistance)
{
// calculate distance value first
float distValue = 0.0;
if(distance<maxDistance) {
distValue = 1.0 - (distance/maxDistance);
}

// consider fix priority
float result = fixPriority + (1.0-fixPriority) * distValue;
}

Very important sounds would get a value of 1.0 (play always). A fix priority of 0 would mean, that a sound purely depends on distance.
Few categories would be enough:
1.0 : very important, never cull (NPC directly speaking with player)
0.8: important, but could be culled (other NPCs)
0.5: main scene/ambient sound
0.0: detail scene sounds, just to improve the sound ambient, but not really necessary

This topic is closed to new replies.

Advertisement