| 60 | // consuming code must call sourcescheduler::releasesource() after use |
| 61 | |
| 62 | source *sourcescheduler::newsource(int priority, const vec &o) |
| 63 | { |
| 64 | if(!sources.length()) |
| 65 | { |
| 66 | DEBUG("empty source collection"); |
| 67 | return NULL; |
| 68 | } |
| 69 | |
| 70 | source *src = NULL; |
| 71 | |
| 72 | // reserve some sources for sounds of higher priority |
| 73 | int reserved = (SP_HIGHEST-priority)*soundschedreserve; |
| 74 | DEBUGVAR(reserved); |
| 75 | |
| 76 | // search unused source |
| 77 | loopv(sources) |
| 78 | { |
| 79 | if(!sources[i]->locked && reserved--<=0) |
| 80 | { |
| 81 | src = sources[i]; |
| 82 | DEBUGVAR(src); |
| 83 | break; |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | if(!src) |
| 88 | { |
| 89 | DEBUG("no empty source found"); |
| 90 | |
| 91 | // low priority sounds can't replace others |
| 92 | if(SP_LOW==priority) |
| 93 | { |
| 94 | DEBUG("low prio sound aborted"); |
| 95 | return NULL; |
| 96 | } |
| 97 | |
| 98 | // try replacing a used source |
| 99 | // score our sound |
| 100 | const float dist = o.iszero() ? 0.0f : camera1->o.dist(o); |
| 101 | const float score = (priority*soundschedpriorityscore) - (dist*soundscheddistancescore); |
| 102 | |
| 103 | // score other sounds |
| 104 | float worstscore = 0.0f; |
| 105 | source *worstsource = NULL; |
| 106 | |
| 107 | loopv(sources) |
| 108 | { |
| 109 | source *s = sources[i]; |
| 110 | if(s->priority==SP_HIGHEST) continue; // highest priority sounds can't be replaced |
| 111 | |
| 112 | const vec & otherpos = s->position(); |
| 113 | float otherdist = otherpos.iszero() ? 0.0f : camera1->o.dist(otherpos); |
| 114 | float otherscore = (s->priority*soundschedpriorityscore) - (otherdist*soundscheddistancescore) + soundschedoldbonus; |
| 115 | if(!worstsource || otherscore < worstscore) |
| 116 | { |
| 117 | worstsource = s; |
| 118 | worstscore = otherscore; |
| 119 | } |