On Monday 10 November 2008 04:27:07 pm slytron wrote:
> I realize that most sound cards can only mix 32 or 64 sounds at a time.
> The question is does a sound card hardware channel get allocated when a
> buffer is loaded with alBufferData and attached with AL_BUFFER or is the
> hardware channel only in use while the sound is playing?
Generally the hardware channel is in use while a buffer is attached to a
source. So setting a source with alSourcei(source,AL_BUFFER,0); will release
the hardware channels. Note that this isn't gauranteed by the spec, but AFAIK
all current hardware drivers behave this way.
The one thing to watch out for though, is that an implementation may only
generate enough sources for each one to play a mono sound (multichannel
buffers may take up multiple hardware channels, too). What you'll probably
have to do is hold a pool of sources, and pick from them as you need one. So,
at your program's start, you could have:
vector<ALuint> Sources;
...
while(1) {
ALuint src;
alGenSources(1, &src);
if(alGetError() != AL_NO_ERROR)
break;
Sources.push_back(src);
}
Since they don't have attached buffers, they won't be taking up hardware
channels yet. Then when you want to play a sound:
void myObject::PlaySound(const string &name, bool looping
/*, other parameters*/)
{
// Get the buffer based on the given name. If it's the first time it's
// used, it can be loaded into an AL buffer then cached globally to be
// returned immediately on subsequent calls
ALuint buffer = GetBufferByName(name);
if(!buffer) // failed to load sound
return;
// Make sure there's a useable source and get it
if(Sources.size() == 0)
{
// if not, you'll have to kill a current sound based on distance,
// gain, and priority (find the sound with the lowest priority and is
// quietest based on distance and gain; if it has lesser priority, or
// equal priority but is quieter, than the sound trying to play, force
// it to stop)
// if there's still no sources (ie. no sounds could be killed), just
// skip
if(Sources.size() == 0)
return;
}
this->source = Sources.back();
Sources.pop_back();
...set source properties...
alSourcei(this->source, AL_LOOPING, looping?AL_TURE:AL_FALSE);
alSourcei(this->source, AL_BUFFER, buffer);
if(alGetError() != AL_NO_ERROR)
{
// failed to setup the sound. return the source to the pool
Sources.push_back(this->source);
this->source = 0;
return;
}
alSourcePlay(this->source);
alGetError();
}
Then about 20 to 30 times a second, you'll want to update the sound. You can
check then to make sure the sound is still playing.
void myObject::UpdateSound()
{
if(!this->source) // no sound to update
return;
ALint state;
alGetSourcei(this->source, AL_SOURCE_STATE, &state);
if(state == AL_STOPPED)
{
// source stopped playing. free the channel and return the source to
// the pool
alSourceRewind(this->source);
alSourcei(this->source, AL_BUFFER, 0);
Sources.push_back(this->source);
this->source = 0;
return;
}
...update parameters...
}
This is similar to a method I used in a project, and is rather scalable. It
works well even with limited sources (32) in high-sound-count environments
(at least 80 trying to play). The higher-level logic will have to check if
the object's supposed to be playing a looping sound and make sure it's still
playing, periodically trying to restart it if its not.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel