git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@6561 e016b1c5-ed68-44aa-a2f7-31cac88cffde
164 lines
4.0 KiB
C++
164 lines
4.0 KiB
C++
// AC sound scheduler, manages available sound sources.
|
|
// It keeps a set of reserved sources for each priority level to avoid running out of sources by floods of low-priority sounds.
|
|
// Under load it uses priority and distance information to reassign its resources.
|
|
|
|
#include "cube.h"
|
|
|
|
#define DEBUGCOND (audiodebug==1)
|
|
|
|
VARP(soundschedpriorityscore, 0, 100, 1000);
|
|
VARP(soundscheddistancescore, 0, 5, 1000);
|
|
VARP(soundschedoldbonus, 0, 100, 1000);
|
|
VARP(soundschedreserve, 0, 2, 100);
|
|
|
|
sourcescheduler *sourcescheduler::inst;
|
|
|
|
sourcescheduler::sourcescheduler()
|
|
{
|
|
}
|
|
|
|
sourcescheduler &sourcescheduler::instance()
|
|
{
|
|
if(inst==NULL) inst = new sourcescheduler();
|
|
return *inst;
|
|
}
|
|
|
|
void sourcescheduler::init(int numsoundchannels)
|
|
{
|
|
this->numsoundchannels = numsoundchannels;
|
|
int newchannels = numsoundchannels - sources.length();
|
|
if(newchannels < 0)
|
|
{
|
|
loopv(sources)
|
|
{
|
|
source *src = sources[i];
|
|
if(src->locked) continue;
|
|
sources.remove(i--);
|
|
delete src;
|
|
if(sources.length() <= numsoundchannels) break;
|
|
}
|
|
}
|
|
else loopi(newchannels)
|
|
{
|
|
source *src = new source();
|
|
if(src->valid) sources.add(src);
|
|
else
|
|
{
|
|
DELETEP(src);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sourcescheduler::reset()
|
|
{
|
|
loopv(sources) sources[i]->reset();
|
|
sources.deletecontents();
|
|
}
|
|
|
|
// returns a free sound source (channel)
|
|
// consuming code must call sourcescheduler::releasesource() after use
|
|
|
|
source *sourcescheduler::newsource(int priority, const vec &o)
|
|
{
|
|
if(!sources.length())
|
|
{
|
|
DEBUG("empty source collection");
|
|
return NULL;
|
|
}
|
|
|
|
source *src = NULL;
|
|
|
|
// reserve some sources for sounds of higher priority
|
|
int reserved = (SP_HIGHEST-priority)*soundschedreserve;
|
|
DEBUGVAR(reserved);
|
|
|
|
// search unused source
|
|
loopv(sources)
|
|
{
|
|
if(!sources[i]->locked && reserved--<=0)
|
|
{
|
|
src = sources[i];
|
|
DEBUGVAR(src);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!src)
|
|
{
|
|
DEBUG("no empty source found");
|
|
|
|
// low priority sounds can't replace others
|
|
if(SP_LOW==priority)
|
|
{
|
|
DEBUG("low prio sound aborted");
|
|
return NULL;
|
|
}
|
|
|
|
// try replacing a used source
|
|
// score our sound
|
|
const float dist = o.iszero() ? 0.0f : camera1->o.dist(o);
|
|
const float score = (priority*soundschedpriorityscore) - (dist*soundscheddistancescore);
|
|
|
|
// score other sounds
|
|
float worstscore = 0.0f;
|
|
source *worstsource = NULL;
|
|
|
|
loopv(sources)
|
|
{
|
|
source *s = sources[i];
|
|
if(s->priority==SP_HIGHEST) continue; // highest priority sounds can't be replaced
|
|
|
|
const vec & otherpos = s->position();
|
|
float otherdist = otherpos.iszero() ? 0.0f : camera1->o.dist(otherpos);
|
|
float otherscore = (s->priority*soundschedpriorityscore) - (otherdist*soundscheddistancescore) + soundschedoldbonus;
|
|
if(!worstsource || otherscore < worstscore)
|
|
{
|
|
worstsource = s;
|
|
worstscore = otherscore;
|
|
}
|
|
}
|
|
|
|
// pick worst source and replace it
|
|
if(worstsource && score>worstscore)
|
|
{
|
|
src = worstsource;
|
|
src->onreassign(); // inform previous owner about the take-over
|
|
DEBUG("replaced sound of same prio");
|
|
}
|
|
}
|
|
|
|
if(!src)
|
|
{
|
|
DEBUG("sound aborted, no channel takeover possible");
|
|
return NULL;
|
|
}
|
|
|
|
src->reset(); // default settings
|
|
src->lock(); // exclusive lock
|
|
src->priority = priority;
|
|
return src;
|
|
}
|
|
|
|
// give source back to the pool
|
|
void sourcescheduler::releasesource(source *src)
|
|
{
|
|
ASSERT(src);
|
|
ASSERT(src->locked); // detect double release
|
|
|
|
if(!src) return;
|
|
|
|
DEBUG("unlocking source");
|
|
|
|
src->unlock();
|
|
|
|
if(sources.length() > numsoundchannels)
|
|
{
|
|
sources.removeobj(src);
|
|
delete src;
|
|
DEBUG("source deleted");
|
|
}
|
|
}
|
|
|
|
|