OpenAL with multiple distance models

OpenAL is a great library to manage 3D surround in your application. For the FPS game AssaultCube I rewrote the sound related code to use OpenAL instead of simple stereo output. There are different distance models to calculate the effective gain (volume) of the sound sources: inverse distance, exponential distance, linear distance, etc. For FPS games the inverse distance models seems to fit best, it just sounds more realistic than simple linear models. Now the problem with inverse models is that no matter how far away the sound source is, the volume will never completely drop down to 0, you will always hear it, this is a real issue:

  • Processing almost silent sounds is a waste of resources that could be used otherwise. The sound channels for mixing are usually limited to 32 (!) on most hardware.
  • You can not limit the sound to a specific radius e.g. to make it present in a single room/area only.

Now you could just disable the distance model using alDistanceModel(AL_NONE) and write your own code to handle all gain calculations yourself. However for AssaultCube I found a better solution, the important sources in the game such as sounds from players are using the inverse distance model, on the other hand all map sound entities that are placed in certain areas as well as low priority sounds such as footsteps use my own distance model. Because OpenAL allows only one distance model to be active, we need to bypass the distance model calculation for these sounds:

alSourcef(id, AL_ROLLOFF_FACTOR, 0.0f);
alSource3f(id, AL_POSITION, 0.0, 0.0, 0.0);

This way the source is always on the same position as the listener, causing the gain value to stay at the maximum. Now that we know that OpenAL won’t touch this source’s gain anymore, we can calculate it using our own rules:

float dist = camera1->o.dist(vec(e->x, e->y, e->z));
float gain = 0.0f;
// clamp to full gain (attr3 is a object "size" property)
if(dist <= e->attr3) gain = 1.0f;
// linear calc (attr2 is a "radius" property)
else if(dist <= e->attr2) gain = 1.0f - dist/(float)e->attr2;
alSourcef(id, AL_GAIN, gain);

Now this object uses our own linear model while the other more important objects still rely on the better but expensive inverse model. I think this is the best solution to the problem regarding code size and simplicity.


2 Responses to “OpenAL with multiple distance models”

  1. 1 GinBlog82 November 1, 2011 at 11:43 am

    This article shows how the OpenAL are not great at all. I had a lot of problems with the stereo panning and I never imagined that i should create two sources to handle it. I’m wondering… what were they thinking? The fact that the OpenAL can simulate a 3d space is not related with the possibility to handle two different parts of the same space: the left and the right side! And why? Because we have only two ears and the stereo is the first need… after the invention of the telegraph?!? 😉 If I have to use openal in the first place is because they are cross-platform and only in the second place because they can simulate a 3d space. The same thing talking about the distance model: only one model for the entire OpenAL context? I mean, are they stupid or what? If the first necessity is to simulate a 3d space, then it’s more and more important that I can choose between different models because the world is large and the nature of different sound sources could be unpredictible. It’s not hard to understand, and how you show in your article, it’s not difficult or expensive to program. I repeat: are they stupid or what? Anyway, there is a little mistake in your code:

    if(dist >= e->attr3) gain = 0.0f;
    else if(dist attr2) gain = 1.0f – dist/(float)e->attr2;
    alSourcef(id, AL_GAIN, gain);

    Now it’s better 😉 The only lack in this approach is that you don’t have the spatial information of the source.

  2. 2 jacoblee2 November 4, 2014 at 4:23 am

    I’m using OpenAL in my iPhone project to create sounds that attenuate when farther away from the listener.However – I also want to play some sound effects that shall not be attenuated by distance.So far I solved that by using stereo sounds, which don’t get attenuated. But now I’m adding a lot of voiceacting which takes quite some space – so I want them to be mono and now have the problem again that they get attenuated by distance.My next solution was to set “AL_MIN_GAIN” of the source playing the voice samples to 1.0, but this seems to be working only on the simulator, not on the device.Are there other ways to play sound effects with openAL that shall not be attenuated by distance?My major work is to generate barcode in rdlc,so i am new to this filed,can anyone helpe me?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: