Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 25, 2009, 10:23:58 PM (14 years ago)
Author:
rgrieder
Message:

Merged presentation2 branch back to trunk.
Major new features:

  • Actual GUI with settings, etc.
  • Improved space ship steering (human interaction)
  • Rocket fire and more particle effects
  • Advanced sound framework
Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/orxonox/sound/SoundManager.cc

    r5929 r6417  
    2222 *   Author:
    2323 *       Erwin 'vaiursch' Herrsche
     24 *       Kevin Young
     25 *       Reto Grieder
    2426 *   Co-authors:
    2527 *      ...
     
    3032
    3133#include <AL/alut.h>
     34#include <utility>
    3235
    3336#include "util/Exception.h"
    3437#include "util/Math.h"
    3538#include "util/ScopeGuard.h"
     39#include "util/Clock.h"
     40#include "core/ConfigValueIncludes.h"
     41#include "core/CoreIncludes.h"
    3642#include "core/GameMode.h"
    3743#include "core/ScopedSingletonManager.h"
     44#include "core/Resource.h"
     45#include "SoundBuffer.h"
     46#include "BaseSound.h"
     47#include "AmbientSound.h"
     48#include "WorldSound.h"
    3849
    3950namespace orxonox
    4051{
    41     SoundManager* SoundManager::singletonPtr_s = NULL;
    4252    ManageScopedSingleton(SoundManager, ScopeID::Graphics, true);
    4353
     54    std::string SoundManager::getALErrorString(ALenum code)
     55    {
     56        switch (code)
     57        {
     58        case AL_NO_ERROR:          return "No error";
     59        case AL_INVALID_NAME:      return "Invalid AL parameter name";
     60        case AL_INVALID_ENUM:      return "Invalid AL enum";
     61        case AL_INVALID_VALUE:     return "Invalid AL value";
     62        case AL_INVALID_OPERATION: return "Invalid AL operation";
     63        case AL_OUT_OF_MEMORY:     return "AL reports out of memory";
     64        default:                   return "Unknown AL error";
     65        }
     66    }
     67
    4468    SoundManager::SoundManager()
    45     {
    46         if (!alutInitWithoutContext(NULL,NULL))
    47             ThrowException(InitialisationFailed, "OpenAL ALUT error: " << alutGetErrorString(alutGetError()));
     69        : effectsPoolSize_(0)
     70    {
     71        RegisterRootObject(SoundManager);
     72
     73        // See whether we even want to load
     74        bool bDisableSound_ = false;
     75        SetConfigValue(bDisableSound_, false);
     76        if (bDisableSound_)
     77            ThrowException(InitialisationAborted, "Sound: Not loading at all");
     78
     79        if (!alutInitWithoutContext(NULL, NULL))
     80            ThrowException(InitialisationFailed, "Sound Error: ALUT initialisation failed: " << alutGetErrorString(alutGetError()));
    4881        Loki::ScopeGuard alutExitGuard = Loki::MakeGuard(&alutExit);
    4982
    50         COUT(3) << "OpenAL: Opening sound device..." << std::endl;
     83/*
     84        // Get list of available sound devices and display them
     85        const char* devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
     86        char* device = new char[strlen(devices)+1];
     87        strcpy(device, devices);
     88        std::string renderDevice;
     89        SetConfigValue(renderDevice, std::string(device)).description("Sound device used for rendering");
     90        COUT(4) << "Sound: Available devices: ";
     91        while (true)
     92        {
     93            this->deviceNames_.push_back(devices);
     94            COUT(4) << '"' << devices << "\", ";
     95            devices += strlen(devices) + 1;
     96            if (*devices == '\0')
     97                break;
     98        }
     99        COUT(4) << std::endl;
     100
     101        // Open the selected device
     102        COUT(3) << "Sound: Opening device \"" << renderDevice << '\' << std::endl;
     103        this->device_ = alcOpenDevice(renderDevice.c_str());
     104*/
    51105        this->device_ = alcOpenDevice(NULL);
    52106        if (this->device_ == NULL)
    53107        {
    54             COUT(0) << "OpenaAL: Could not open sound device. Have you installed OpenAL?" << std::endl;
     108            COUT(1) << "Sound: Could not open sound device. Have you installed OpenAL?" << std::endl;
    55109#ifdef ORXONOX_PLATFORM_WINDOWS
    56             COUT(0) << "Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
     110            COUT(1) << "Sound: Just getting the DLL with the dependencies is not enough for Windows (esp. Windows 7)!" << std::endl;
    57111#endif
    58             ThrowException(InitialisationFailed, "OpenAL error: Could not open sound device.");
     112            ThrowException(InitialisationFailed, "Sound Error: Could not open sound device.");
    59113        }
    60114        Loki::ScopeGuard closeDeviceGuard = Loki::MakeGuard(&alcCloseDevice, this->device_);
    61115
    62         COUT(3) << "OpenAL: Sound device opened" << std::endl;
     116        // Create sound context and make it the currently used one
    63117        this->context_ = alcCreateContext(this->device_, NULL);
    64118        if (this->context_ == NULL)
    65             ThrowException(InitialisationFailed, "OpenAL error: Could not create sound context");
     119            ThrowException(InitialisationFailed, "Sound Error: Could not create ALC context");
    66120        Loki::ScopeGuard desroyContextGuard = Loki::MakeGuard(&alcDestroyContext, this->context_);
    67 
    68         if (alcMakeContextCurrent(this->context_) == AL_TRUE)
    69             COUT(3) << "OpenAL: Context " << this->context_ << " loaded" << std::endl;
    70 
    71         COUT(4) << "Sound: OpenAL ALUT version: " << alutGetMajorVersion() << "." << alutGetMinorVersion() << std::endl;
    72 
    73         const char* str = alutGetMIMETypes(ALUT_LOADER_BUFFER);
    74         if (str == NULL)
    75             COUT(2) << "OpenAL ALUT error: " << alutGetErrorString(alutGetError()) << std::endl;
     121        if (!alcMakeContextCurrent(this->context_))
     122            ThrowException(InitialisationFailed, "Sound Error: Could not use ALC context");
     123
     124        GameMode::setPlaysSound(true);
     125        Loki::ScopeGuard resetPlaysSoundGuard = Loki::MakeGuard(&GameMode::setPlaysSound, false);
     126
     127        // Get some information about the sound
     128        if (const char* version = alGetString(AL_VERSION))
     129            COUT(4) << "Sound: --- OpenAL Version: " << version << std::endl;
     130        if (const char* vendor = alGetString(AL_VENDOR))
     131            COUT(4) << "Sound: --- OpenAL Vendor : " << vendor << std::endl;
     132        if (const char* types = alutGetMIMETypes(ALUT_LOADER_BUFFER))
     133            COUT(4) << "Sound: --- Supported MIME Types: " << types << std::endl;
    76134        else
    77             COUT(4) << "OpenAL ALUT supported MIME types: " << str << std::endl;
    78 
    79         GameMode::setPlaysSound(true);
     135            COUT(2) << "Sound Warning: MIME Type retrieval failed: " << alutGetErrorString(alutGetError()) << std::endl;
     136
     137        this->mute_[SoundType::All]     = 1.0f;
     138        this->mute_[SoundType::Music]   = 1.0f;
     139        this->mute_[SoundType::Effects] = 1.0f;
     140
     141        this->setConfigValues();
     142
     143        // Try to get at least one source
     144        ALuint source;
     145        alGenSources(1, &source);
     146        if (!alGetError() && alIsSource(source))
     147            this->availableSoundSources_.push_back(source);
     148        else
     149            ThrowException(InitialisationFailed, "Sound Error: Could not create even a single source");
     150        // Create a few initial sources
     151        this->createSoundSources(this->minSources_ - 1);
     152
    80153        // Disarm guards
    81154        alutExitGuard.Dismiss();
    82155        closeDeviceGuard.Dismiss();
    83156        desroyContextGuard.Dismiss();
     157        resetPlaysSoundGuard.Dismiss();
     158
     159        COUT(4) << "Sound: Initialisation complete" << std::endl;
    84160    }
    85161
    86162    SoundManager::~SoundManager()
    87163    {
     164        // Erase fade lists because of the smart pointers
     165        this->fadeInList_.clear();
     166        this->fadeOutList_.clear();
     167
     168        // If there are still used buffers around, well, that's just very bad...
     169        if (this->soundBuffers_.size() != this->effectsPool_.size())
     170            COUT(1) << "Sound Error: Some sound buffers are still in use but OpenAL is about to shut down. Fix this!" << std::endl;
     171        // Empty buffer pool and buffer list
     172        this->effectsPool_.clear();
     173        this->soundBuffers_.clear();
     174
     175        // There should not be any sources in use anymore
     176        if (!this->usedSoundSources_.empty())
     177            COUT(1) << "Sound Error: Some sound sources are still in use but OpenAL is about to shut down. Fix this!" << std::endl;
     178        while (!this->availableSoundSources_.empty())
     179        {
     180            alDeleteSources(1, &this->availableSoundSources_.back());
     181            this->availableSoundSources_.pop_back();
     182        }
     183
    88184        GameMode::setPlaysSound(false);
     185
     186        // Relieve context to destroy it
     187        if (!alcMakeContextCurrent(NULL))
     188            COUT(1) << "Sound Error: Could not unset ALC context" << std::endl;
    89189        alcDestroyContext(this->context_);
     190        if (ALCenum error = alcGetError(this->device_))
     191        {
     192            if (error == AL_INVALID_OPERATION)
     193                COUT(1) << "Sound Error: Could not destroy ALC context because it is the current one" << std::endl;
     194            else
     195                COUT(1) << "Sound Error: Could not destroy ALC context because it is invalid" << std::endl;
     196        }
     197#ifdef AL_VERSION_1_1
     198        if (!alcCloseDevice(this->device_))
     199            COUT(1) << "Sound Error: Could not destroy ALC device. This might be because there are still buffers in use!" << std::endl;
     200#else
    90201        alcCloseDevice(this->device_);
    91         alutExit();
     202#endif
     203        if (!alutExit())
     204            COUT(1) << "Sound Error: Closing ALUT failed: " << alutGetErrorString(alutGetError()) << std::endl;
     205    }
     206
     207    void SoundManager::setConfigValues()
     208    {
     209        SetConfigValue(crossFadeStep_, 0.2f)
     210            .description("Determines how fast sounds should fade, per second.")
     211            .callback(this, &SoundManager::checkFadeStepValidity);
     212
     213        SetConfigValueAlias(volume_[SoundType::All], "soundVolume_", 1.0f)
     214            .description("Defines the overall volume.")
     215            .callback(this, &SoundManager::checkSoundVolumeValidity);
     216        SetConfigValueAlias(volume_[SoundType::Music], "ambientVolume_", 1.0f)
     217            .description("Defines the ambient volume.")
     218            .callback(this, &SoundManager::checkAmbientVolumeValidity);
     219        SetConfigValueAlias(volume_[SoundType::Effects], "effectsVolume_", 1.0f)
     220            .description("Defines the effects volume.")
     221            .callback(this, &SoundManager::checkEffectsVolumeValidity);
     222
     223        SetConfigValue(minSources_, 16)
     224            .description("Minimum number of sources being generated (if possible)");
     225        SetConfigValue(maxSources_, 1024)
     226            .description("Maximum number of sources to be made available");
     227    }
     228
     229    void SoundManager::preUpdate(const Clock& time)
     230    {
     231        this->processCrossFading(time.getDeltaTime());
     232
     233        // Check whether a sound object has stopped playing
     234        for (unsigned int i = 0; i < this->usedSoundSources_.size(); ++i)
     235        {
     236            ALint state;
     237            alGetSourcei(this->usedSoundSources_[i].first, AL_SOURCE_STATE, &state);
     238            if (state == AL_STOPPED)
     239            {
     240                this->usedSoundSources_[i].second->stop();
     241                --i;
     242            }
     243        }
     244    }
     245
     246    void SoundManager::checkFadeStepValidity()
     247    {
     248        if (crossFadeStep_ <= 0.0 || crossFadeStep_ >= 1.0 )
     249        {
     250            COUT(2) << "Sound warning: fade step out of range, ignoring change." << std::endl;
     251            ResetConfigValue(crossFadeStep_);
     252        }
     253    }
     254
     255    void SoundManager::checkVolumeValidity(SoundType::Value type)
     256    {
     257        float clampedVolume = clamp(this->volume_[type], 0.0f, 1.0f);
     258        if (clampedVolume != this->volume_[type])
     259            COUT(2) << "Sound warning: Volume setting (" << type << ") out of range, clamping." << std::endl;
     260        this->updateVolume(type);
     261    }
     262
     263    void SoundManager::setVolume(float vol, SoundType::Value type)
     264    {
     265        if (type < 0 || type > SoundType::Effects)
     266            return;
     267        this->volume_[type] = vol;
     268        this->checkVolumeValidity(type);
     269    }
     270
     271    float SoundManager::getVolume(SoundType::Value type)
     272    {
     273        if (type < 0 || type > SoundType::Effects)
     274            return 0.0f;
     275        return this->volume_[type];
     276    }
     277
     278    float SoundManager::getRealVolume(SoundType::Value type)
     279    {
     280        if (type != SoundType::Music && type != SoundType::Effects)
     281            return 0.0f;
     282        return this->volume_[SoundType::All] * this->mute_[SoundType::All] * this->volume_[type] * this->mute_[type];
     283    }
     284
     285    void SoundManager::updateVolume(SoundType::Value type)
     286    {
     287        switch(type)
     288        {
     289        case SoundType::All:
     290            for (ObjectList<BaseSound>::iterator it = ObjectList<BaseSound>::begin(); it != ObjectList<BaseSound>::end(); ++it)
     291                (*it)->updateVolume();
     292            break;
     293        case SoundType::Music:
     294            for (ObjectList<AmbientSound>::iterator it = ObjectList<AmbientSound>::begin(); it != ObjectList<AmbientSound>::end(); ++it)
     295                (*it)->updateVolume();
     296            break;
     297        case SoundType::Effects:
     298            for (ObjectList<WorldSound>::iterator it = ObjectList<WorldSound>::begin(); it != ObjectList<WorldSound>::end(); ++it)
     299                (*it)->updateVolume();
     300            break;
     301        default:
     302            assert(false);
     303        }
     304    }
     305
     306    void SoundManager::toggleMute(SoundType::Value type)
     307    {
     308        if (type < 0 || type > SoundType::Effects)
     309            return;
     310        this->mute_[type] = (this->mute_[type] == 0) ? 1.0f : 0.0f;
     311        this->updateVolume(type);
     312    }
     313
     314    bool SoundManager::getMute(SoundType::Value type)
     315    {
     316        if (type < 0 || type > SoundType::Effects)
     317            return true;
     318        return (this->mute_[type] == 0);
    92319    }
    93320
     
    103330    {
    104331        // update listener orientation
    105         Vector3 up = orientation.xAxis(); // just a wild guess
    106         Vector3 at = orientation.zAxis();
    107 
    108         ALfloat orient[6] = { at.x, at.y, at.z,
    109                               up.x, up.y, up.z };
    110 
    111         alListenerfv(AL_POSITION, orient);
     332        const Vector3& direction = -orientation.zAxis();
     333        const Vector3& up = orientation.yAxis();
     334
     335        ALfloat orient[6] = { direction.x, direction.y, direction.z, up.x, up.y, up.z };
     336
     337        alListenerfv(AL_ORIENTATION, orient);
    112338        ALenum error = alGetError();
    113339        if (error == AL_INVALID_VALUE)
    114340            COUT(2) << "Sound: OpenAL: Invalid listener orientation" << std::endl;
    115341    }
     342
     343    void SoundManager::registerAmbientSound(AmbientSound* newAmbient)
     344    {
     345        if (newAmbient != NULL)
     346        {
     347            for (AmbientList::const_iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
     348            {
     349                if (it->first == newAmbient)
     350                {
     351                    COUT(2) << "Sound warning: Will not play an AmbientSound twice." << std::endl;
     352                    return;
     353                }
     354            }
     355
     356            if (!this->ambientSounds_.empty())
     357            {
     358                this->fadeOut(ambientSounds_.front().first);
     359            }
     360            this->ambientSounds_.push_front(std::make_pair(newAmbient, false));
     361            newAmbient->doPlay();
     362            this->fadeIn(newAmbient);
     363        }
     364    }
     365
     366    void SoundManager::unregisterAmbientSound(AmbientSound* oldAmbient)
     367    {
     368        if (oldAmbient == NULL || ambientSounds_.empty())
     369            return;
     370
     371        if (this->ambientSounds_.front().first == oldAmbient)
     372        {
     373            this->fadeOut(oldAmbient);
     374            this->ambientSounds_.pop_front();
     375            if (!this->ambientSounds_.empty())
     376            {
     377                if (!this->ambientSounds_.front().second) // Not paused before
     378                {
     379                    this->ambientSounds_.front().first->doPlay();
     380                }
     381                this->fadeIn(this->ambientSounds_.front().first);
     382            }
     383        }
     384        else
     385        {
     386            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
     387            {
     388                if (it->first == oldAmbient)
     389                {
     390                    this->fadeOut(oldAmbient);
     391                    this->ambientSounds_.erase(it);
     392                    break;
     393                }
     394            }
     395        }
     396    }
     397
     398    void SoundManager::pauseAmbientSound(AmbientSound* ambient)
     399    {
     400        if (ambient != NULL)
     401        {
     402            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
     403            {
     404                if (it->first == ambient)
     405                {
     406                    it->second = true;
     407                    this->fadeOut(it->first);
     408                    return;
     409                }
     410            }
     411        }
     412    }
     413
     414    void SoundManager::fadeIn(const SmartPtr<AmbientSound>& sound)
     415    {
     416        // If we're already fading out --> remove that
     417        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it++)
     418        {
     419            if (*it == sound)
     420            {
     421                this->fadeOutList_.erase(it);
     422                break;
     423            }
     424        }
     425        // No duplicate entries
     426        if (std::find(this->fadeInList_.begin(), this->fadeInList_.end(), sound) == this->fadeInList_.end())
     427            this->fadeInList_.push_back(sound);
     428    }
     429
     430    void SoundManager::fadeOut(const SmartPtr<AmbientSound>& sound)
     431    {
     432        // If we're already fading in --> remove that
     433        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeInList_.begin(); it != this->fadeInList_.end(); it++)
     434        {
     435            if (*it == sound)
     436            {
     437                this->fadeInList_.erase(it);
     438                break;
     439            }
     440        }
     441        // No duplicate entries
     442        if (std::find(this->fadeOutList_.begin(), this->fadeOutList_.end(), sound) == this->fadeOutList_.end())
     443            this->fadeOutList_.push_back(sound);
     444    }
     445
     446    void SoundManager::processCrossFading(float dt)
     447    {
     448
     449        // Hacky solution to the fade delay while loading a level.
     450        if(dt > 0.2)
     451        {
     452            return;
     453        }
     454
     455        // FADE IN
     456        for (std::list<SmartPtr<AmbientSound> >::iterator it= this->fadeInList_.begin(); it != this->fadeInList_.end(); )
     457        {
     458            if ((*it)->getVolume() + this->crossFadeStep_*dt > 1.0f)
     459            {
     460                (*it)->setVolume(1.0f);
     461                this->fadeInList_.erase(it++);
     462            }
     463            else
     464            {
     465                (*it)->setVolume((*it)->getVolume() + this->crossFadeStep_*dt);
     466                ++it;
     467            }
     468        }
     469
     470        // FADE OUT
     471        for (std::list<SmartPtr<AmbientSound> >::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); )
     472        {
     473            if ((*it)->getVolume() - this->crossFadeStep_*dt < 0.0f)
     474            {
     475                (*it)->setVolume(0.0f);
     476
     477                // If sound is in the ambient list --> pause
     478                for (AmbientList::const_iterator it2 = this->ambientSounds_.begin(); it2 != this->ambientSounds_.end(); ++it2)
     479                {
     480                    if (it2->first == *it)
     481                    {
     482                        (*it)->doPause();
     483                        break;
     484                    }
     485                }
     486                // If not pause (by loop above for instance) --> stop
     487                if (!(*it)->isPaused())
     488                    (*it)->doStop();
     489
     490                this->fadeOutList_.erase(it++);
     491            }
     492            else
     493            {
     494                (*it)->setVolume((*it)->getVolume() - this->crossFadeStep_*dt);
     495                ++it;
     496            }
     497        }
     498    }
     499
     500    shared_ptr<SoundBuffer> SoundManager::getSoundBuffer(const std::string& filename)
     501    {
     502        shared_ptr<SoundBuffer> buffer;
     503        // Check active or pooled buffers
     504        SoundBufferMap::const_iterator it = this->soundBuffers_.find(filename);
     505        if (it != this->soundBuffers_.end())
     506        {
     507            buffer = it->second;
     508
     509            // Remove from effects pool if not active used before
     510            if (buffer->poolIterator_ != this->effectsPool_.end())
     511            {
     512                this->effectsPoolSize_ -= buffer->getSize();
     513                this->effectsPool_.erase(buffer->poolIterator_);
     514                buffer->poolIterator_ = this->effectsPool_.end();
     515            }
     516        }
     517        else
     518        {
     519            try
     520            {
     521                buffer.reset(new SoundBuffer(filename, this->effectsPool_.end()));
     522            }
     523            catch (...)
     524            {
     525                COUT(1) << Exception::handleMessage() << std::endl;
     526                return buffer;
     527            }
     528            this->soundBuffers_[filename] = buffer;
     529        }
     530        return buffer;
     531    }
     532
     533    void SoundManager::releaseSoundBuffer(const shared_ptr<SoundBuffer>& buffer, bool bPoolBuffer)
     534    {
     535        // Check if others are still using the buffer
     536        if (buffer.use_count() != 2)
     537            return;
     538        SoundBufferMap::iterator it = this->soundBuffers_.find(buffer->getFilename());
     539        if (it != this->soundBuffers_.end())
     540        {
     541            if (bPoolBuffer)
     542            {
     543                // Pool already too large?
     544                while (this->effectsPoolSize_ + it->second->getSize() > this->maxEffectsPoolSize_s && !this->effectsPool_.empty())
     545                {
     546                    shared_ptr<SoundBuffer> bufferDel = this->effectsPool_.back();
     547                    this->effectsPoolSize_ -= bufferDel->getSize();
     548                    bufferDel->poolIterator_ = this->effectsPool_.end();
     549                    this->effectsPool_.pop_back();
     550                    // Remove from buffer map too
     551                    SoundBufferMap::iterator itDel = this->soundBuffers_.find(bufferDel->getFilename());
     552                    if (itDel != this->soundBuffers_.end())
     553                        this->soundBuffers_.erase(itDel);
     554                }
     555                // Put buffer into the pool
     556                this->effectsPoolSize_ += it->second->getSize();
     557                this->effectsPool_.push_front(it->second);
     558                it->second->poolIterator_ = this->effectsPool_.begin();
     559            }
     560            else
     561                this->soundBuffers_.erase(it);
     562        }
     563    }
     564
     565    ALuint SoundManager::getSoundSource(BaseSound* object)
     566    {
     567        if (!this->availableSoundSources_.empty())
     568        {
     569            ALuint source = this->availableSoundSources_.back();
     570            this->availableSoundSources_.pop_back();
     571            this->usedSoundSources_.push_back(std::make_pair(source, object));
     572            return source;
     573        }
     574        else
     575        {
     576            if (this->usedSoundSources_.size() < this->maxSources_)
     577            {
     578                ALuint source;
     579                alGenSources(1, &source);
     580                // Try to create new sources (50% more, but at least one)
     581                if (alIsSource(source) && !alGetError())
     582                {
     583                    this->usedSoundSources_.push_back(std::make_pair(source, object));
     584                    return source;
     585                }
     586            }
     587            // Return no source ID
     588            ALuint source = 123456789;
     589            while (alIsSource(++source));
     590            return source;
     591        }
     592    }
     593
     594    void SoundManager::releaseSoundSource(ALuint source)
     595    {
     596#ifndef NDEBUG
     597        for (std::vector<ALuint>::const_iterator it = this->availableSoundSources_.begin(); it != this->availableSoundSources_.end(); ++it)
     598            assert((*it) != source);
     599#endif
     600        this->availableSoundSources_.push_back(source);
     601        for (std::vector<std::pair<ALuint, BaseSound*> >::iterator it = this->usedSoundSources_.begin();
     602            it != this->usedSoundSources_.end(); ++it)
     603        {
     604            if (it->first == source)
     605            {
     606                this->usedSoundSources_.erase(it);
     607                break;
     608            }
     609        }
     610        int used = std::max((unsigned int)(this->usedSoundSources_.size()), this->minSources_);
     611        // Subtract those we added in the statement above trough std::max
     612        int available = (int)this->availableSoundSources_.size() - (used - (int)this->usedSoundSources_.size());
     613        // Delete sources again to free resources if appropriate (more than 50% more available than used)
     614        int toDelete = available - used / 2;
     615        while (toDelete-- > 0)
     616        {
     617            alDeleteSources(1, &this->availableSoundSources_.back());
     618            if (alGetError())
     619                COUT(1) << "Sound Error: Failed to delete a source --> lost forever" << std::endl;
     620            this->availableSoundSources_.pop_back();
     621        }
     622    }
     623
     624    unsigned int SoundManager::createSoundSources(unsigned int n)
     625    {
     626        unsigned int count = this->availableSoundSources_.size() + this->usedSoundSources_.size();
     627        while (count < this->maxSources_ && count <= n)
     628        {
     629            ALuint source;
     630            alGenSources(1, &source);
     631            if (alIsSource(source) && !alGetError())
     632                this->availableSoundSources_.push_back(source);
     633            else
     634                break;
     635            ++count;
     636        }
     637        return count - this->availableSoundSources_.size() - this->usedSoundSources_.size();
     638    }
    116639}
Note: See TracChangeset for help on using the changeset viewer.