diff --git a/Core/GameEngine/Include/Common/AudioEventRTS.h b/Core/GameEngine/Include/Common/AudioEventRTS.h index f38f1e5417a..15d441dd428 100644 --- a/Core/GameEngine/Include/Common/AudioEventRTS.h +++ b/Core/GameEngine/Include/Common/AudioEventRTS.h @@ -199,14 +199,27 @@ class AudioEventRTS PortionToPlay m_portionToPlayNext; ///< Which portion (attack, sound, decay) should be played next? }; -class DynamicAudioEventRTS : public MemoryPoolObject +class DynamicAudioEventRTS : public MemoryPoolObject, public RefCountClass, public AudioEventRTS { MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DynamicAudioEventRTS, "DynamicAudioEventRTS" ) public: - DynamicAudioEventRTS() { } - DynamicAudioEventRTS(const AudioEventRTS& a) : m_event(a) { } + DynamicAudioEventRTS() {} + DynamicAudioEventRTS( const AsciiString& eventName ) : AudioEventRTS(eventName) {} + DynamicAudioEventRTS( const AsciiString& eventName, ObjectID ownerID ) : AudioEventRTS(eventName, ownerID) {} + DynamicAudioEventRTS( const AsciiString& eventName, DrawableID drawableID ) : AudioEventRTS(eventName, drawableID) {} + DynamicAudioEventRTS( const AsciiString& eventName, const Coord3D *positionOfAudio ) : AudioEventRTS(eventName, positionOfAudio) {} - AudioEventRTS m_event; + DynamicAudioEventRTS(const AudioEventRTS& a) : AudioEventRTS(a) {} + DynamicAudioEventRTS& operator=( const AudioEventRTS& right ) + { + *static_cast(this) = right; + return *this; + } + + void Delete_This() override + { + deleteInstance(this); + } }; EMPTY_DTOR(DynamicAudioEventRTS) diff --git a/Core/GameEngine/Include/Common/AudioRequest.h b/Core/GameEngine/Include/Common/AudioRequest.h index 3174fe85a8a..fd9ac0f670e 100644 --- a/Core/GameEngine/Include/Common/AudioRequest.h +++ b/Core/GameEngine/Include/Common/AudioRequest.h @@ -30,8 +30,9 @@ #include "Common/GameAudio.h" #include "Common/GameMemory.h" +#include "Common/AudioHandleSpecialValues.h" -class AudioEventRTS; +class DynamicAudioEventRTS; enum RequestType CPP_11(: Int) { @@ -45,14 +46,18 @@ struct AudioRequest : public MemoryPoolObject MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AudioRequest, "AudioRequest" ) public: - AudioEventRTS* releasePendingEvent(); + + AudioRequest() + : m_request(AR_Play) + , m_pendingEvent(nullptr) + , m_handleToInteractOn(AHSV_Error) + , m_requiresCheckForSample(false) + , m_requestStop(false) + {} RequestType m_request; - union - { - AudioEventRTS *m_pendingEvent; - AudioHandle m_handleToInteractOn; - }; - Bool m_usePendingEvent; + RefCountPtr m_pendingEvent; + AudioHandle m_handleToInteractOn; Bool m_requiresCheckForSample; + Bool m_requestStop; // Let the audio play and finish but stop looping if it is looping }; diff --git a/Core/GameEngine/Include/Common/GameAudio.h b/Core/GameEngine/Include/Common/GameAudio.h index 024e6ef2ca9..c9369fd6107 100644 --- a/Core/GameEngine/Include/Common/GameAudio.h +++ b/Core/GameEngine/Include/Common/GameAudio.h @@ -244,8 +244,6 @@ class AudioManager : public SubsystemInterface // on zoom. virtual void set3DVolumeAdjustment( Real volumeAdjustment ); - virtual Bool has3DSensitiveStreamsPlaying() const = 0; - virtual void *getHandleForBink() = 0; virtual void releaseHandleForBink() = 0; @@ -257,9 +255,9 @@ class AudioManager : public SubsystemInterface virtual void setListenerPosition( const Coord3D *newListenerPos, const Coord3D *newListenerOrientation ); virtual const Coord3D *getListenerPosition() const; - virtual AudioRequest *allocateAudioRequest( Bool useAudioEvent ); + virtual AudioRequest *allocateAudioRequest(); virtual void releaseAudioRequest( AudioRequest *requestToRelease ); - virtual void appendAudioRequest( AudioRequest *m_request ); + virtual void appendAudioRequest( AudioRequest *request ); virtual void processRequestList(); virtual AudioEventInfo *newAudioEventInfo( AsciiString newEventName ); @@ -269,9 +267,6 @@ class AudioManager : public SubsystemInterface const AudioSettings *getAudioSettings() const; const MiscAudio *getMiscAudio() const; - // This function should only be called by AudioManager, MusicManager and SoundManager - virtual void releaseAudioEventRTS( AudioEventRTS *&eventToRelease ); - // For INI AudioSettings *friend_getAudioSettings(); MiscAudio *friend_getMiscAudio(); diff --git a/Core/GameEngine/Include/Common/GameMusic.h b/Core/GameEngine/Include/Common/GameMusic.h index cd47a3f8ece..346cb402ade 100644 --- a/Core/GameEngine/Include/Common/GameMusic.h +++ b/Core/GameEngine/Include/Common/GameMusic.h @@ -102,10 +102,10 @@ class MusicManager MusicManager(); virtual ~MusicManager(); - void playTrack( AudioEventRTS *eventToUse ); + void playTrack( DynamicAudioEventRTS *eventToUse ); void stopTrack( AudioHandle eventToRemove ); - virtual void addAudioEvent(AudioEventRTS *eventToAdd); // pre-copied + virtual void addAudioEvent( DynamicAudioEventRTS *eventToAdd ); // pre-copied virtual void removeAudioEvent( AudioHandle eventToRemove ); void setVolume( Real m_volume ); diff --git a/Core/GameEngine/Include/Common/GameSounds.h b/Core/GameEngine/Include/Common/GameSounds.h index f684f11edda..c63dbc3280c 100644 --- a/Core/GameEngine/Include/Common/GameSounds.h +++ b/Core/GameEngine/Include/Common/GameSounds.h @@ -45,8 +45,8 @@ #include "Common/GameAudio.h" #include "Common/GameType.h" -// Forward declarations class AudioEventRTS; +class DynamicAudioEventRTS; class SoundManager : public SubsystemInterface { @@ -67,7 +67,7 @@ class SoundManager : public SubsystemInterface virtual void setCameraAudibleDistance( Real audibleDistance ); virtual Real getCameraAudibleDistance(); - virtual void addAudioEvent(AudioEventRTS *&eventToAdd); // pre-copied + virtual Bool addAudioEvent(DynamicAudioEventRTS *eventToAdd); // pre-copied // empty string means that this sound wasn't found or some error occurred. CHECK FOR EMPTY STRING. virtual AsciiString getFilenameForPlayFromAudioEvent( const AudioEventRTS *eventToGetFrom ); diff --git a/Core/GameEngine/Include/GameClient/VideoPlayer.h b/Core/GameEngine/Include/GameClient/VideoPlayer.h index 98a7d4c8d67..a7380a2114c 100644 --- a/Core/GameEngine/Include/GameClient/VideoPlayer.h +++ b/Core/GameEngine/Include/GameClient/VideoPlayer.h @@ -245,6 +245,8 @@ class VideoPlayerInterface : public SubsystemInterface virtual const FieldParse *getFieldParse() const = 0; ///< Return the field parse info virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ) = 0; ///< Notify the video player that they can now ask for an audio handle, or they need to give theirs up. + + virtual void setVolume( Real volume ) = 0; ///< Push a new speech volume to the video player's audio output }; @@ -299,6 +301,13 @@ class VideoPlayer : public VideoPlayerInterface }; +class NullVideoPlayer : public VideoPlayer +{ + public: + + virtual void setVolume( Real ) override { } +}; + extern VideoPlayerInterface *TheVideoPlayer; //---------------------------------------------------------------------------- diff --git a/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp b/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp index 36876f35449..6fcf9b80c98 100644 --- a/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp +++ b/Core/GameEngine/Source/Common/Audio/AudioRequest.cpp @@ -30,20 +30,4 @@ AudioRequest::~AudioRequest() { - if (m_usePendingEvent) - { - delete m_pendingEvent; - } -} - -AudioEventRTS* AudioRequest::releasePendingEvent() -{ - if (m_usePendingEvent) - { - m_usePendingEvent = false; - AudioEventRTS* event = m_pendingEvent; - m_pendingEvent = nullptr; - return event; - } - return nullptr; } diff --git a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp index f60607fd845..a569ea998b6 100644 --- a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp @@ -439,7 +439,8 @@ AudioHandle AudioManager::addAudioEvent(const AudioEventRTS *eventToAdd) return AHSV_NotForLocal; } - AudioEventRTS *audioEvent = MSGNEW("AudioEventRTS") AudioEventRTS(*eventToAdd); // poolify + RefCountPtr audioEvent; + audioEvent.Assign_No_Add_Ref(newInstance(DynamicAudioEventRTS)(*eventToAdd)); audioEvent->setPlayingHandle( allocateNewHandle() ); audioEvent->generateFilename(); // which file are we actually going to play? eventToAdd->setPlayingAudioIndex( audioEvent->getPlayingAudioIndex() ); @@ -456,7 +457,6 @@ AudioHandle AudioManager::addAudioEvent(const AudioEventRTS *eventToAdd) #if RETAIL_COMPATIBLE_CRC if (notForLocal) { - releaseAudioEventRTS(audioEvent); return AHSV_NotForLocal; } #endif @@ -466,21 +466,22 @@ AudioHandle AudioManager::addAudioEvent(const AudioEventRTS *eventToAdd) #ifdef INTENSIVE_AUDIO_DEBUG DEBUG_LOG((" - culled due to muting (%d).", audioEvent->getVolume())); #endif - releaseAudioEventRTS(audioEvent); return AHSV_Muted; } if (soundType == AT_Music) { - m_music->addAudioEvent(audioEvent); + m_music->addAudioEvent(audioEvent.Peek()); } else { - //Possible to nuke audioEvent inside. - m_sound->addAudioEvent(audioEvent); + if (!m_sound->addAudioEvent(audioEvent.Peek())) + { + audioEvent.Clear(); + } } - if( audioEvent ) + if( audioEvent != nullptr ) { return audioEvent->getPlayingHandle(); } @@ -578,7 +579,7 @@ void AudioManager::removeAudioEvent(AudioHandle audioEvent) return; } - AudioRequest *req = allocateAudioRequest( false ); + AudioRequest *req = allocateAudioRequest(); req->m_handleToInteractOn = audioEvent; req->m_request = AR_Stop; appendAudioRequest( req ); @@ -709,7 +710,12 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) m_scriptMusicVolume = volume; } - m_musicVolume = m_scriptMusicVolume * m_systemMusicVolume; + const Real newVolume = m_scriptMusicVolume * m_systemMusicVolume; + if (m_musicVolume != newVolume) + { + m_musicVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Sound) { @@ -719,7 +725,12 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) m_scriptSoundVolume = volume; } - m_soundVolume = m_scriptSoundVolume * m_systemSoundVolume; + const Real newVolume = m_scriptSoundVolume * m_systemSoundVolume; + if (m_soundVolume != newVolume) + { + m_soundVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Sound3D) { @@ -728,7 +739,13 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) } else { m_scriptSound3DVolume = volume; } - m_sound3DVolume = m_scriptSound3DVolume * m_systemSound3DVolume; + + const Real newVolume = m_scriptSound3DVolume * m_systemSound3DVolume; + if (m_sound3DVolume != newVolume) + { + m_sound3DVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Speech) { @@ -737,10 +754,14 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) } else { m_scriptSpeechVolume = volume; } - m_speechVolume = m_scriptSpeechVolume * m_systemSpeechVolume; - } + const Real newVolume = m_scriptSpeechVolume * m_systemSpeechVolume; + if (m_speechVolume != newVolume) + { + m_speechVolume = newVolume; m_volumeHasChanged = true; + } + } } //------------------------------------------------------------------------------------------------- @@ -761,17 +782,13 @@ Real AudioManager::getVolume( AudioAffect whichToGet ) //------------------------------------------------------------------------------------------------- void AudioManager::set3DVolumeAdjustment( Real volumeAdjustment ) { - m_sound3DVolume = volumeAdjustment * m_scriptSound3DVolume * m_systemSound3DVolume; - - // clamp - if (m_sound3DVolume < 0.0f) - m_sound3DVolume = 0.0f; + const Real newVolume = clamp(0.0f, volumeAdjustment * m_scriptSound3DVolume * m_systemSound3DVolume, 1.0f); - if (m_sound3DVolume > 1.0f) - m_sound3DVolume = 1.0f; - - if ( ! has3DSensitiveStreamsPlaying() ) - m_volumeHasChanged = TRUE; + if (m_sound3DVolume != newVolume) + { + m_sound3DVolume = newVolume; + m_volumeHasChanged = true; + } } //------------------------------------------------------------------------------------------------- @@ -788,10 +805,9 @@ const Coord3D *AudioManager::getListenerPosition() const } //------------------------------------------------------------------------------------------------- -AudioRequest *AudioManager::allocateAudioRequest( Bool useAudioEvent ) +AudioRequest *AudioManager::allocateAudioRequest() { AudioRequest *audioReq = newInstance(AudioRequest); - audioReq->m_usePendingEvent = useAudioEvent; audioReq->m_requiresCheckForSample = false; return audioReq; } @@ -805,9 +821,9 @@ void AudioManager::releaseAudioRequest( AudioRequest *requestToRelease ) } //------------------------------------------------------------------------------------------------- -void AudioManager::appendAudioRequest( AudioRequest *m_request ) +void AudioManager::appendAudioRequest( AudioRequest *request ) { - m_audioRequests.push_back(m_request); + m_audioRequests.push_back(request); } //------------------------------------------------------------------------------------------------- @@ -815,10 +831,9 @@ void AudioManager::appendAudioRequest( AudioRequest *m_request ) void AudioManager::removeAllAudioRequests() { std::list::iterator it; - for ( it = m_audioRequests.begin(); it != m_audioRequests.end(); it++ ) { + for ( it = m_audioRequests.begin(); it != m_audioRequests.end(); ++it ) { releaseAudioRequest( *it ); } - m_audioRequests.clear(); } @@ -1047,17 +1062,10 @@ Bool AudioManager::shouldPlayLocally(const AudioEventRTS *audioEvent) //------------------------------------------------------------------------------------------------- AudioHandle AudioManager::allocateNewHandle() { - // note, intenionally a post increment rather than a pre increment. + // note, intentionally a post increment rather than a pre increment. return theAudioHandlePool++; } -//------------------------------------------------------------------------------------------------- -void AudioManager::releaseAudioEventRTS( AudioEventRTS *&eventToRelease ) -{ - delete eventToRelease; - eventToRelease = nullptr; -} - //------------------------------------------------------------------------------------------------- void AudioManager::muteAudio( MuteAudioReason reason ) { diff --git a/Core/GameEngine/Source/Common/Audio/GameMusic.cpp b/Core/GameEngine/Source/Common/Audio/GameMusic.cpp index 5e05c6ee4d3..3c87003b4da 100644 --- a/Core/GameEngine/Source/Common/Audio/GameMusic.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameMusic.cpp @@ -95,10 +95,10 @@ MusicManager::~MusicManager() } //------------------------------------------------------------------------------------------------- -void MusicManager::playTrack( AudioEventRTS *eventToUse ) +void MusicManager::playTrack( DynamicAudioEventRTS *eventToUse ) { - AudioRequest *audioRequest = TheAudio->allocateAudioRequest( true ); - audioRequest->m_pendingEvent = eventToUse; + AudioRequest *audioRequest = TheAudio->allocateAudioRequest(); + audioRequest->m_pendingEvent.Assign_Add_Ref(eventToUse); audioRequest->m_request = AR_Play; TheAudio->appendAudioRequest( audioRequest ); } @@ -106,14 +106,14 @@ void MusicManager::playTrack( AudioEventRTS *eventToUse ) //------------------------------------------------------------------------------------------------- void MusicManager::stopTrack( AudioHandle eventToRemove ) { - AudioRequest *audioRequest = TheAudio->allocateAudioRequest( false ); + AudioRequest *audioRequest = TheAudio->allocateAudioRequest(); audioRequest->m_handleToInteractOn = eventToRemove; audioRequest->m_request = AR_Stop; TheAudio->appendAudioRequest( audioRequest ); } //------------------------------------------------------------------------------------------------- -void MusicManager::addAudioEvent( AudioEventRTS *eventToAdd ) +void MusicManager::addAudioEvent( DynamicAudioEventRTS *eventToAdd ) { playTrack( eventToAdd ); } diff --git a/Core/GameEngine/Source/Common/Audio/GameSounds.cpp b/Core/GameEngine/Source/Common/Audio/GameSounds.cpp index b6be88480b1..25987911795 100644 --- a/Core/GameEngine/Source/Common/Audio/GameSounds.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameSounds.cpp @@ -132,19 +132,20 @@ Real SoundManager::getCameraAudibleDistance() } //------------------------------------------------------------------------------------------------- -void SoundManager::addAudioEvent(AudioEventRTS *&eventToAdd) +Bool SoundManager::addAudioEvent(DynamicAudioEventRTS *eventToAdd) { if (canPlayNow(eventToAdd)) { #ifdef INTENSIVE_AUDIO_DEBUG DEBUG_LOG((" - appended to request list with handle '%d'.", (UnsignedInt) eventToAdd->getPlayingHandle())); #endif - AudioRequest *audioRequest = TheAudio->allocateAudioRequest( true ); - audioRequest->m_pendingEvent = eventToAdd; + AudioRequest *audioRequest = TheAudio->allocateAudioRequest(); + audioRequest->m_pendingEvent.Assign_Add_Ref(eventToAdd); audioRequest->m_request = AR_Play; TheAudio->appendAudioRequest(audioRequest); - } else { - TheAudio->releaseAudioEventRTS(eventToAdd); + return true; } + + return false; } //------------------------------------------------------------------------------------------------- diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index c1452990414..2c73a39872e 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -1167,23 +1167,22 @@ void INI::parseICoord2D( INI* ini, void * /*instance*/, void *store, const void* void INI::parseDynamicAudioEventRTS( INI *ini, void * /*instance*/, void *store, const void* userData ) { const char *token = ini->getNextToken(); - DynamicAudioEventRTS** theSound = (DynamicAudioEventRTS**)store; + RefCountPtr* theSound = (RefCountPtr*)store; // translate the string into a sound if (stricmp(token, "NoSound") == 0) { - deleteInstance(*theSound); - *theSound = nullptr; + theSound->Clear(); } else { if (*theSound == nullptr) - *theSound = newInstance(DynamicAudioEventRTS); - (*theSound)->m_event.setEventName(AsciiString(token)); + *theSound = Create_No_Add_Ref(newInstance(DynamicAudioEventRTS)); + (*theSound)->setEventName(AsciiString(token)); } if (*theSound) - TheAudio->getInfoForAudioEvent(&(*theSound)->m_event); + TheAudio->getInfoForAudioEvent(theSound->Peek()); } //------------------------------------------------------------------------------------------------- diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index d2d108ddaad..f2c1911e634 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -26,81 +26,94 @@ #include "WWLib/mutex.h" class AudioEventRTS; +class DynamicAudioEventRTS; enum { MAXPROVIDERS = 64 }; enum PlayingAudioType CPP_11(: Int) { - PAT_Sample, - PAT_3DSample, - PAT_Stream, - PAT_INVALID + PAT_Sample, + PAT_3DSample, + PAT_Stream, + PAT_INVALID }; enum PlayingStatus CPP_11(: Int) { - PS_Playing, - PS_Stopping, ///< Is about to be stopped - PS_Stopped, ///< Is about to be released + PS_Playing, + PS_Stopping, ///< Is about to be stopped + PS_Stopped, ///< Is about to be released }; enum PlayingWhich CPP_11(: Int) { - PW_Attack, - PW_Sound, - PW_Decay, - PW_INVALID + PW_Attack, + PW_Sound, + PW_Decay, + PW_INVALID }; struct PlayingAudio { - union - { - HSAMPLE m_sample; - H3DSAMPLE m_3DSample; - HSTREAM m_stream; - }; - - AudioEventRTS* m_audioEventRTS; - void* m_file; // The file that was opened to play this - PlayingAudioType m_type; - volatile PlayingStatus m_status; // This member is adjusted by another running thread. - Short m_framesFaded; - Bool m_fade; - Bool m_cleanupAudioEventRTS; - - PlayingAudio() - : m_sample(nullptr) - , m_audioEventRTS(nullptr) - , m_file(nullptr) - , m_type(PAT_INVALID) - , m_status(PS_Playing) - , m_framesFaded(0) - , m_fade(false) - , m_cleanupAudioEventRTS(true) - {} - - static_assert(sizeof(m_status) == sizeof(long), "Must be size of long, because it is used with Interlocked functions"); + union + { + HSAMPLE m_sample; + H3DSAMPLE m_3DSample; + HSTREAM m_stream; + }; + + RefCountPtr m_audioEventRTS; + void *m_file; // The file that was opened to play this + PlayingAudioType m_type; + volatile PlayingStatus m_status; // This member is adjusted by another running thread. + Short m_framesFaded; + Bool m_fade; + volatile Bool m_rerequestOnNextUpdate; + volatile Bool m_requestStop; // Let the audio finish but stop looping if it is looping + + PlayingAudio() + : m_sample(nullptr) + , m_audioEventRTS(nullptr) + , m_file(nullptr) + , m_type(PAT_INVALID) + , m_status(PS_Playing) + , m_framesFaded(0) + , m_fade(false) + , m_rerequestOnNextUpdate(false) + , m_requestStop(false) + {} + + Bool isPlaying() const + { + return m_status == PS_Playing; + } + + Bool isPlayingOrRequested() const + { + return m_status == PS_Playing || m_rerequestOnNextUpdate; + } + + static_assert(sizeof(m_status) == sizeof(long), "Must be size of long, because it is used with Interlocked functions"); }; struct ProviderInfo { - AsciiString name; - HPROVIDER id; - Bool m_isValid; + AsciiString name; + HPROVIDER id; + Bool m_isValid; }; struct OpenAudioFile { - AILSOUNDINFO m_soundInfo; - void* m_file; - UnsignedInt m_openCount; - UnsignedInt m_fileSize; + AILSOUNDINFO m_soundInfo; + void *m_file; + UnsignedInt m_openCount; + UnsignedInt m_fileSize; - Bool m_compressed; // if the file was compressed, then we need to free it with a miles function. + Bool m_compressed; // if the file was compressed, then we need to free it with a miles function. - // Note: OpenAudioFile does not own this m_eventInfo, and should not delete it. - const AudioEventInfo* m_eventInfo; // Not mutable, unlike the one on AudioEventRTS. + // Note: OpenAudioFile does not own this m_eventInfo, and should not delete it. + const AudioEventInfo *m_eventInfo; // Not mutable, unlike the one on AudioEventRTS. }; typedef std::hash_map< AsciiString, OpenAudioFile, rts::hash, rts::equal_to/**/> OpenFilesHash; @@ -108,232 +121,230 @@ typedef OpenFilesHash::iterator OpenFilesHashIt; class AudioFileCache { -public: - AudioFileCache(); - - // Protected by mutex - virtual ~AudioFileCache(); - void* openFile(AudioEventRTS* eventToOpenFrom); - void closeFile(void* fileToClose); - void setMaxSize(UnsignedInt size); - // End Protected by mutex - - // Note: These functions should be used for informational purposes only. For speed reasons, - // they are not protected by the mutex, so they are not guaranteed to be valid if called from - // outside the audio cache. They should be used as a rough estimate only. - UnsignedInt getCurrentlyUsedSize() const { return m_currentlyUsedSize; } - UnsignedInt getMaxSize() const { return m_maxSize; } - -protected: - void releaseOpenAudioFile(OpenAudioFile* fileToRelease); - - // This function will return TRUE if it was able to free enough space, and FALSE otherwise. - Bool freeEnoughSpaceForSample(const OpenAudioFile& sampleThatNeedsSpace); - - OpenFilesHash m_openFiles; - UnsignedInt m_currentlyUsedSize; - UnsignedInt m_maxSize; - HANDLE m_mutex; - const char* m_mutexName; + public: + AudioFileCache(); + + // Protected by mutex + virtual ~AudioFileCache(); + void *openFile( AudioEventRTS *eventToOpenFrom ); + void closeFile( void *fileToClose ); + void setMaxSize( UnsignedInt size ); + // End Protected by mutex + + // Note: These functions should be used for informational purposes only. For speed reasons, + // they are not protected by the mutex, so they are not guaranteed to be valid if called from + // outside the audio cache. They should be used as a rough estimate only. + UnsignedInt getCurrentlyUsedSize() const { return m_currentlyUsedSize; } + UnsignedInt getMaxSize() const { return m_maxSize; } + + protected: + void releaseOpenAudioFile( OpenAudioFile *fileToRelease ); + + // This function will return TRUE if it was able to free enough space, and FALSE otherwise. + Bool freeEnoughSpaceForSample(const OpenAudioFile& sampleThatNeedsSpace); + + OpenFilesHash m_openFiles; + UnsignedInt m_currentlyUsedSize; + UnsignedInt m_maxSize; + HANDLE m_mutex; + const char *m_mutexName; }; class MilesAudioManager : public AudioManager { -public: + public: #if defined(RTS_DEBUG) - virtual void audioDebugDisplay(DebugDisplayInterface* dd, void*, FILE* fp = nullptr) override; - virtual AudioHandle addAudioEvent(const AudioEventRTS* eventToAdd) override; ///< Add an audio event (event must be declared in an INI file) + virtual void audioDebugDisplay(DebugDisplayInterface *dd, void *, FILE *fp = nullptr ) override; + virtual AudioHandle addAudioEvent( const AudioEventRTS *eventToAdd ) override; ///< Add an audio event (event must be declared in an INI file) #endif - // from AudioDevice - virtual void init() override; - virtual void postProcessLoad() override; - virtual void reset() override; - virtual void update() override; + // from AudioDevice + virtual void init() override; + virtual void postProcessLoad() override; + virtual void reset() override; + virtual void update() override; - MilesAudioManager(); - virtual ~MilesAudioManager() override; + MilesAudioManager(); + virtual ~MilesAudioManager() override; - virtual AsciiString nextMusicTrack() override; - virtual AsciiString prevMusicTrack() override; - virtual Bool isMusicPlaying() const override; - virtual Bool hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const override; + virtual AsciiString nextMusicTrack() override; + virtual AsciiString prevMusicTrack() override; + virtual Bool isMusicPlaying() const override; + virtual Bool hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const override; - virtual void openDevice() override; - virtual void closeDevice() override; - virtual void* getDevice() override { return m_digitalHandle; } + virtual void openDevice() override; + virtual void closeDevice() override; + virtual void *getDevice() override { return m_digitalHandle; } + + virtual void stopAudio( AudioAffect which ) override; + virtual void pauseAudio( AudioAffect which ) override; + virtual void resumeAudio( AudioAffect which ) override; + virtual void pauseAmbient( Bool shouldPause ) override; + + virtual void killAudioEventImmediately( AudioHandle audioEvent ) override; + + ///< Return whether the current audio is playing or not. + ///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE + virtual Bool isCurrentlyPlaying( AudioHandle handle ) override; - virtual void stopAudio(AudioAffect which) override; - virtual void pauseAudio(AudioAffect which) override; - virtual void resumeAudio(AudioAffect which) override; - virtual void pauseAmbient(Bool shouldPause) override; + virtual void notifyOfAudioCompletion( UnsignedInt handle, UnsignedInt flags ) override; ///< Is called on MSS Timer thread + virtual PlayingAudio *findPlayingAudioFrom( UnsignedInt handle, UnsignedInt flags ); - virtual void killAudioEventImmediately(AudioHandle audioEvent) override; + virtual UnsignedInt getProviderCount() const override; + virtual AsciiString getProviderName( UnsignedInt providerNum ) const override; + virtual UnsignedInt getProviderIndex( AsciiString providerName ) const override; + virtual void selectProvider( UnsignedInt providerNdx ) override; + virtual void unselectProvider() override; + virtual UnsignedInt getSelectedProvider() const override; + virtual void setSpeakerType( UnsignedInt speakerType ) override; + virtual UnsignedInt getSpeakerType() override; - ///< Return whether the current audio is playing or not. - ///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE - virtual Bool isCurrentlyPlaying(AudioHandle handle) override; + virtual void *getHandleForBink() override; + virtual void releaseHandleForBink() override; - virtual void notifyOfAudioCompletion(UnsignedInt handle, UnsignedInt flags) override; - virtual PlayingAudio* findPlayingAudioFrom(UnsignedInt handle, UnsignedInt flags); + virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override; - virtual UnsignedInt getProviderCount() const override; - virtual AsciiString getProviderName(UnsignedInt providerNum) const override; - virtual UnsignedInt getProviderIndex(AsciiString providerName) const override; - virtual void selectProvider(UnsignedInt providerNdx) override; - virtual void unselectProvider() override; - virtual UnsignedInt getSelectedProvider() const override; - virtual void setSpeakerType(UnsignedInt speakerType) override; - virtual UnsignedInt getSpeakerType() override; + virtual UnsignedInt getNum2DSamples() const override; + virtual UnsignedInt getNum3DSamples() const override; + virtual UnsignedInt getNumStreams() const override; + virtual UnsignedInt getNumAvailable2DSamples() const override; + virtual UnsignedInt getNumAvailable3DSamples() const override; - virtual void* getHandleForBink() override; - virtual void releaseHandleForBink() override; + virtual Bool doesViolateLimit( AudioEventRTS *event ) const override; + virtual Bool isPlayingLowerPriority( AudioEventRTS *event ) const override; + virtual Bool isPlayingAlready( AudioEventRTS *event ) const override; + virtual Bool isObjectPlayingVoice( UnsignedInt objID ) const override; + Bool killLowestPrioritySoundImmediately( AudioEventRTS *event ); + AudioEventRTS* findLowestPrioritySound( AudioEventRTS *event ); - virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override; + virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override; - virtual UnsignedInt getNum2DSamples() const override; - virtual UnsignedInt getNum3DSamples() const override; - virtual UnsignedInt getNumStreams() const override; - virtual UnsignedInt getNumAvailable2DSamples() const override; - virtual UnsignedInt getNumAvailable3DSamples() const override; + virtual void removePlayingAudio( AsciiString eventName ) override; + virtual void removeAllDisabledAudio() override; + + virtual void processRequestList() override; + virtual void processPlayingList(); + virtual void processFadingList(); - virtual Bool doesViolateLimit(AudioEventRTS* event) const override; - virtual Bool isPlayingLowerPriority(AudioEventRTS* event) const override; - virtual Bool isPlayingAlready(AudioEventRTS* event) const override; - virtual Bool isObjectPlayingVoice(UnsignedInt objID) const override; - Bool killLowestPrioritySoundImmediately(AudioEventRTS* event); - AudioEventRTS* findLowestPrioritySound(AudioEventRTS* event); + Bool shouldProcessRequestThisFrame( AudioRequest *req ) const; + void adjustRequest( AudioRequest *req ); + Bool checkForSample( AudioRequest *req ); + + virtual void setHardwareAccelerated(Bool accel) override; + virtual void setSpeakerSurround(Bool surround) override; + + virtual void setPreferredProvider(AsciiString provider) override { m_pref3DProvider = provider; } + virtual void setPreferredSpeaker(AsciiString speakerType) override { m_prefSpeaker = speakerType; } + + virtual Real getFileLengthMS( AsciiString strToLoad ) const override; + + virtual void closeAnySamplesUsingFile( const void *fileToClose ) override; + + protected: + // 3-D functions + virtual void setDeviceListenerPosition() override; + const Coord3D *getCurrentPositionFromEvent( AudioEventRTS *event ); + Bool isOnScreen( const Coord3D *pos ) const; + Real getEffectiveVolume(AudioEventRTS *event) const; + + // Looping functions + Bool startNextLoop( PlayingAudio *playing ); + + void playStream( AudioEventRTS *event, HSTREAM stream ); + // Returns the file handle for attachment to the PlayingAudio structure + void *playSample( AudioEventRTS *event, HSAMPLE sample ); + void *playSample3D( AudioEventRTS *event, H3DSAMPLE sample3D ); + + void buildProviderList(); + void createListener(); + void initDelayFilter(); + Bool isValidProvider(); + void initSamplePools(); + void processRequest( AudioRequest *req ); + + void playAudioEvent( AudioRequest* req ); + void stopAudioEvent( AudioHandle handle ); + void pauseAudioEvent( AudioHandle handle ); + + void *loadFileForRead( AudioEventRTS *eventToLoadFrom ); + void closeFile( void *fileRead ); + + PlayingAudio *allocatePlayingAudio(); + void releaseMilesHandles( PlayingAudio *playing ); + void releasePlayingAudio( PlayingAudio *playing ); + void stopPlayingAudio( PlayingAudio *playing ); + void rerequestPlayingAudio( PlayingAudio *playing ); + void rerequestPlayingAudioWhenSignalled( PlayingAudio *playing ); + void fadePlayingAudio( PlayingAudio *playing ); + + PlayingAudio *findActiveMusic( const AsciiString *trackName = nullptr ); + const PlayingAudio *findActiveMusic( const AsciiString* trackName = nullptr ) const; + + void releasePlayingAudioInListIfStopped(std::list &list, CriticalSectionClass &cs); + void stopAllAudioImmediately(); + void freeAllMilesHandles(); + + HSAMPLE getAvailable2DSample( AudioEventRTS *event ); + H3DSAMPLE getAvailable3DSample( AudioEventRTS *event ); + + void adjustPlayingVolume( PlayingAudio *audio ); + + void stopAllSpeech(); + + void initFilters( HSAMPLE sample, AudioEventRTS *eventInfo ); + void initFilters3D( H3DSAMPLE sample, AudioEventRTS *eventInfo, const Coord3D *pos ); + + protected: + ProviderInfo m_provider3D[MAXPROVIDERS]; + UnsignedInt m_providerCount; + UnsignedInt m_selectedProvider; + UnsignedInt m_lastProvider; + UnsignedInt m_selectedSpeakerType; - virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override; + AsciiString m_pref3DProvider; + AsciiString m_prefSpeaker; + + HDIGDRIVER m_digitalHandle; + H3DPOBJECT m_listener; + HPROVIDER m_delayFilter; + + // This is a list of all handles that are forcibly played. They always play as UI sounds. + std::list m_audioForcePlayed; + + // Available handles for play. Note that there aren't handles open in advance for + // streaming things, only 2-D and 3-D sounds. + std::vector m_availableSamples; + std::vector m_available3DSamples; - virtual void removePlayingAudio(AsciiString eventName) override; - virtual void removeAllDisabledAudio() override; + // Currently Playing audio. Useful if we have to preempt it. + // This should rarely if ever happen, as we mirror this in Sounds, and attempt to + // keep preemption from taking place here. + std::list m_playingSounds; + std::list m_playing3DSounds; + std::list m_playingStreams; + + // Currently fading music. We just let it finish fading, then release it. + std::list m_fadingAudio; - virtual void processRequestList() override; - virtual void processPlayingList(); - virtual void processFadingList(); + // TheSuperHackers @fix Erasing from PlayingAudio lists on main thread is not safe when the MSS Timer thread + // needs to iterate the same lists. The critical sections are used to guard writes that will invalidate iterators. + CriticalSectionClass m_playingSoundsCS; + CriticalSectionClass m_playing3DSoundsCS; + CriticalSectionClass m_playingStreamsCS; + CriticalSectionClass m_fadingAudioCS; - Bool shouldProcessRequestThisFrame(AudioRequest* req) const; - void adjustRequest(AudioRequest* req); - Bool checkForSample(AudioRequest* req); - - virtual void setHardwareAccelerated(Bool accel) override; - virtual void setSpeakerSurround(Bool surround) override; - - virtual void setPreferredProvider(AsciiString provider) override { m_pref3DProvider = provider; } - virtual void setPreferredSpeaker(AsciiString speakerType) override { m_prefSpeaker = speakerType; } - - virtual Real getFileLengthMS(AsciiString strToLoad) const override; - - virtual void closeAnySamplesUsingFile(const void* fileToClose) override; - - - virtual Bool has3DSensitiveStreamsPlaying() const override; - - -protected: - // 3-D functions - virtual void setDeviceListenerPosition() override; - const Coord3D* getCurrentPositionFromEvent(AudioEventRTS* event); - Bool isOnScreen(const Coord3D* pos) const; - Real getEffectiveVolume(AudioEventRTS* event) const; - - // Looping functions - Bool startNextLoop(PlayingAudio* looping); - - void playStream(AudioEventRTS* event, HSTREAM stream); - // Returns the file handle for attachment to the PlayingAudio structure - void* playSample(AudioEventRTS* event, HSAMPLE sample); - void* playSample3D(AudioEventRTS* event, H3DSAMPLE sample3D); - - void buildProviderList(); - void createListener(); - void initDelayFilter(); - Bool isValidProvider(); - void initSamplePools(); - void processRequest(AudioRequest* req); - - void playAudioEvent(AudioRequest* req); - void stopAudioEvent(AudioHandle handle); - void pauseAudioEvent(AudioHandle handle); - - void* loadFileForRead(AudioEventRTS* eventToLoadFrom); - void closeFile(void* fileRead); - - PlayingAudio* allocatePlayingAudio(); - void releaseMilesHandles(PlayingAudio* release); - void releasePlayingAudio(PlayingAudio* release); - void stopPlayingAudio(PlayingAudio* release); - void fadePlayingAudio(PlayingAudio* playing); - - PlayingAudio* findActiveMusic(const AsciiString* trackName = nullptr); - const PlayingAudio* findActiveMusic(const AsciiString* trackName = nullptr) const; - - void releasePlayingAudioInListIfStopped(std::list& list, CriticalSectionClass& cs); - void stopAllAudioImmediately(); - void freeAllMilesHandles(); - - HSAMPLE getAvailable2DSample(AudioEventRTS* event); - H3DSAMPLE getAvailable3DSample(AudioEventRTS* event); - - void adjustPlayingVolume(PlayingAudio* audio); - - void stopAllSpeech(); - - void initFilters(HSAMPLE sample, AudioEventRTS* eventInfo); - void initFilters3D(H3DSAMPLE sample, AudioEventRTS* eventInfo, const Coord3D* pos); - -protected: - ProviderInfo m_provider3D[MAXPROVIDERS]; - UnsignedInt m_providerCount; - UnsignedInt m_selectedProvider; - UnsignedInt m_lastProvider; - UnsignedInt m_selectedSpeakerType; - - AsciiString m_pref3DProvider; - AsciiString m_prefSpeaker; - - HDIGDRIVER m_digitalHandle; - H3DPOBJECT m_listener; - HPROVIDER m_delayFilter; - - // This is a list of all handles that are forcibly played. They always play as UI sounds. - std::list m_audioForcePlayed; - - // Available handles for play. Note that there aren't handles open in advance for - // streaming things, only 2-D and 3-D sounds. - std::vector m_availableSamples; - std::vector m_available3DSamples; - - // Currently Playing audio. Useful if we have to preempt it. - // This should rarely if ever happen, as we mirror this in Sounds, and attempt to - // keep preemption from taking place here. - std::list m_playingSounds; - std::list m_playing3DSounds; - std::list m_playingStreams; - - // Currently fading music. We just let it finish fading, then release it. - std::list m_fadingAudio; - - // TheSuperHackers @fix Erasing from PlayingAudio lists on main thread is not safe when the MSS Timer thread - // needs to iterate the same lists. The critical sections are used to guard writes that will invalidate iterators. - CriticalSectionClass m_playingSoundsCS; - CriticalSectionClass m_playing3DSoundsCS; - CriticalSectionClass m_playingStreamsCS; - CriticalSectionClass m_fadingAudioCS; - - AudioFileCache* m_audioCache; - PlayingAudio* m_binkHandle; - UnsignedInt m_num2DSamples; - UnsignedInt m_num3DSamples; - UnsignedInt m_numStreams; + AudioFileCache *m_audioCache; + PlayingAudio *m_binkHandle; + UnsignedInt m_num2DSamples; + UnsignedInt m_num3DSamples; + UnsignedInt m_numStreams; #if defined(RTS_DEBUG) - typedef std::set SetAsciiString; - typedef SetAsciiString::iterator SetAsciiStringIt; - SetAsciiString m_allEventsLoaded; - void dumpAllAssetsUsed(); + typedef std::set SetAsciiString; + typedef SetAsciiString::iterator SetAsciiStringIt; + SetAsciiString m_allEventsLoaded; + void dumpAllAssetsUsed(); #endif }; @@ -344,48 +355,47 @@ class MilesAudioManager : public AudioManager class MilesAudioManagerDummy : public MilesAudioManager { #if defined(RTS_DEBUG) - virtual void audioDebugDisplay(DebugDisplayInterface* dd, void* userData, FILE* fp) override {} + virtual void audioDebugDisplay(DebugDisplayInterface* dd, void* userData, FILE* fp) override {} #endif - virtual void stopAudio(AudioAffect which) override {} - virtual void pauseAudio(AudioAffect which) override {} - virtual void resumeAudio(AudioAffect which) override {} - virtual void pauseAmbient(Bool shouldPause) override {} - virtual void killAudioEventImmediately(AudioHandle audioEvent) override {} - virtual AsciiString nextMusicTrack() override { return AsciiString::TheEmptyString; } - virtual AsciiString prevMusicTrack() override { return AsciiString::TheEmptyString; } - virtual Bool isMusicPlaying() const override { return false; } - virtual Bool hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const override { return false; } - //virtual void openDevice() override {} - //virtual void closeDevice() override {} - //virtual void* getDevice() override { return nullptr; } - virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags) override {} - virtual UnsignedInt getProviderCount() const override { return 0; }; - virtual AsciiString getProviderName(UnsignedInt providerNum) const override { return AsciiString::TheEmptyString; } - virtual UnsignedInt getProviderIndex(AsciiString providerName) const override { return 0; } - virtual void selectProvider(UnsignedInt providerNdx) override {} - virtual void unselectProvider() override {} - virtual UnsignedInt getSelectedProvider() const override { return 0; } - virtual void setSpeakerType(UnsignedInt speakerType) override {} - virtual UnsignedInt getSpeakerType() override { return 0; } - virtual UnsignedInt getNum2DSamples() const override { return 0; } - virtual UnsignedInt getNum3DSamples() const override { return 0; } - virtual UnsignedInt getNumStreams() const override { return 0; } - virtual UnsignedInt getNumAvailable2DSamples() const override { return 0; } - virtual UnsignedInt getNumAvailable3DSamples() const override { return 0; } - virtual Bool doesViolateLimit(AudioEventRTS* event) const override { return false; } - virtual Bool isPlayingLowerPriority(AudioEventRTS* event) const override { return false; } - virtual Bool isPlayingAlready(AudioEventRTS* event) const override { return false; } - virtual Bool isObjectPlayingVoice(UnsignedInt objID) const override { return false; } - virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override {} - virtual void removePlayingAudio(AsciiString eventName) override {} - virtual void removeAllDisabledAudio() override {} - virtual Bool has3DSensitiveStreamsPlaying() const override { return false; } - virtual void* getHandleForBink() override { return nullptr; } - virtual void releaseHandleForBink() override {} - virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override {} - virtual void setPreferredProvider(AsciiString providerNdx) override {} - virtual void setPreferredSpeaker(AsciiString speakerType) override {} - //virtual Real getFileLengthMS(AsciiString strToLoad) const override { return 0.0f; } - virtual void closeAnySamplesUsingFile(const void* fileToClose) override {} - virtual void setDeviceListenerPosition() override {} + virtual void stopAudio(AudioAffect which) override {} + virtual void pauseAudio(AudioAffect which) override {} + virtual void resumeAudio(AudioAffect which) override {} + virtual void pauseAmbient(Bool shouldPause) override {} + virtual void killAudioEventImmediately(AudioHandle audioEvent) override {} + virtual AsciiString nextMusicTrack() override { return AsciiString::TheEmptyString; } + virtual AsciiString prevMusicTrack() override { return AsciiString::TheEmptyString; } + virtual Bool isMusicPlaying() const override { return false; } + virtual Bool hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const override { return false; } + //virtual void openDevice() override {} + //virtual void closeDevice() override {} + //virtual void* getDevice() override { return nullptr; } + virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags) override {} + virtual UnsignedInt getProviderCount() const override { return 0; }; + virtual AsciiString getProviderName(UnsignedInt providerNum) const override { return AsciiString::TheEmptyString; } + virtual UnsignedInt getProviderIndex(AsciiString providerName) const override { return 0; } + virtual void selectProvider(UnsignedInt providerNdx) override {} + virtual void unselectProvider() override {} + virtual UnsignedInt getSelectedProvider() const override { return 0; } + virtual void setSpeakerType(UnsignedInt speakerType) override {} + virtual UnsignedInt getSpeakerType() override { return 0; } + virtual UnsignedInt getNum2DSamples() const override { return 0; } + virtual UnsignedInt getNum3DSamples() const override { return 0; } + virtual UnsignedInt getNumStreams() const override { return 0; } + virtual UnsignedInt getNumAvailable2DSamples() const override { return 0; } + virtual UnsignedInt getNumAvailable3DSamples() const override { return 0; } + virtual Bool doesViolateLimit(AudioEventRTS* event) const override { return false; } + virtual Bool isPlayingLowerPriority(AudioEventRTS* event) const override { return false; } + virtual Bool isPlayingAlready(AudioEventRTS* event) const override { return false; } + virtual Bool isObjectPlayingVoice(UnsignedInt objID) const override { return false; } + virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override {} + virtual void removePlayingAudio(AsciiString eventName) override {} + virtual void removeAllDisabledAudio() override {} + virtual void* getHandleForBink() override { return nullptr; } + virtual void releaseHandleForBink() override {} + virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override {} + virtual void setPreferredProvider(AsciiString providerNdx) override {} + virtual void setPreferredSpeaker(AsciiString speakerType) override {} + //virtual Real getFileLengthMS(AsciiString strToLoad) const override { return 0.0f; } + virtual void closeAnySamplesUsingFile(const void* fileToClose) override {} + virtual void setDeviceListenerPosition() override {} }; diff --git a/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h b/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h index 38047636245..5bfd99adf82 100644 --- a/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h +++ b/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h @@ -101,11 +101,6 @@ class BinkVideoStream : public VideoStream class BinkVideoPlayer : public VideoPlayer { - - protected: - - VideoStreamInterface* createStream( HBINK handle ); - public: // subsytem requirements @@ -127,7 +122,16 @@ class BinkVideoPlayer : public VideoPlayer virtual VideoStreamInterface* load( AsciiString movieTitle ) override; ///< Load video file in to memory for playback virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ) override; + virtual void setVolume( Real volume ) override; virtual void initializeBinkWithMiles(); + + protected: + + VideoStreamInterface* createStream( HBINK handle ); + + private: + + static Int calculateMovieAudioVolume( Real volume ); }; diff --git a/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h b/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h index 2d6e55d7053..3635aa78e02 100644 --- a/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h +++ b/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h @@ -121,6 +121,7 @@ class FFmpegVideoPlayer : public VideoPlayer virtual VideoStreamInterface* load( AsciiString movieTitle ); ///< Load video file in to memory for playback virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ); + virtual void setVolume( Real ) override { } virtual void initializeBinkWithMiles(); }; diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 731910858ee..e1cd3e9dbec 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -72,2903 +72,2981 @@ enum { INFINITE_LOOP_COUNT = 1000000 }; // Callback functions useful for Miles //////////////////////////////////////////////////////////// -static void AILCALLBACK setSampleCompleted(HSAMPLE sampleCompleted); -static void AILCALLBACK set3DSampleCompleted(H3DSAMPLE sample3DCompleted); -static void AILCALLBACK setStreamCompleted(HSTREAM streamCompleted); +static void AILCALLBACK setSampleCompleted( HSAMPLE sampleCompleted ); +static void AILCALLBACK set3DSampleCompleted( H3DSAMPLE sample3DCompleted ); +static void AILCALLBACK setStreamCompleted( HSTREAM streamCompleted ); -static U32 AILCALLBACK streamingFileOpen(char const* fileName, void** file_handle); -static void AILCALLBACK streamingFileClose(void* fileHandle); -static S32 AILCALLBACK streamingFileSeek(void* fileHandle, S32 offset, U32 type); -static U32 AILCALLBACK streamingFileRead(void* fileHandle, void* buffer, U32 bytes); +static U32 AILCALLBACK streamingFileOpen(char const *fileName, void **file_handle); +static void AILCALLBACK streamingFileClose(void *fileHandle); +static S32 AILCALLBACK streamingFileSeek(void *fileHandle, S32 offset, U32 type); +static U32 AILCALLBACK streamingFileRead(void *fileHandle, void *buffer, U32 bytes); //------------------------------------------------------------------------------------------------- MilesAudioManager::MilesAudioManager() : - m_providerCount(0), - m_selectedProvider(PROVIDER_ERROR), - m_selectedSpeakerType(0), - m_lastProvider(PROVIDER_ERROR), - m_digitalHandle(nullptr), - m_num2DSamples(0), - m_num3DSamples(0), - m_numStreams(0), - m_delayFilter(nullptr), - m_binkHandle(nullptr), - m_pref3DProvider(AsciiString::TheEmptyString), - m_prefSpeaker(AsciiString::TheEmptyString) + m_providerCount(0), + m_selectedProvider(PROVIDER_ERROR), + m_selectedSpeakerType(0), + m_lastProvider(PROVIDER_ERROR), + m_digitalHandle(nullptr), + m_num2DSamples(0), + m_num3DSamples(0), + m_numStreams(0), + m_delayFilter(nullptr), + m_binkHandle(nullptr), + m_pref3DProvider(AsciiString::TheEmptyString), + m_prefSpeaker(AsciiString::TheEmptyString) { - m_audioCache = NEW AudioFileCache; + m_audioCache = NEW AudioFileCache; } //------------------------------------------------------------------------------------------------- MilesAudioManager::~MilesAudioManager() { - DEBUG_ASSERTCRASH(m_binkHandle == nullptr, ("Leaked a Bink handle. Chuybregts")); - releaseHandleForBink(); - closeDevice(); - delete m_audioCache; + DEBUG_ASSERTCRASH(m_binkHandle == nullptr, ("Leaked a Bink handle. Chuybregts")); + releaseHandleForBink(); + closeDevice(); + delete m_audioCache; - DEBUG_ASSERTCRASH(this == TheAudio, ("Umm...")); - TheAudio = nullptr; + DEBUG_ASSERTCRASH(this == TheAudio, ("Umm...")); + TheAudio = nullptr; } //------------------------------------------------------------------------------------------------- #if defined(RTS_DEBUG) -AudioHandle MilesAudioManager::addAudioEvent(const AudioEventRTS* eventToAdd) +AudioHandle MilesAudioManager::addAudioEvent( const AudioEventRTS *eventToAdd ) { - if (TheGlobalData->m_preloadReport) { - if (!eventToAdd->getEventName().isEmpty()) { - m_allEventsLoaded.insert(eventToAdd->getEventName()); - } - } + if (TheGlobalData->m_preloadReport) { + if (!eventToAdd->getEventName().isEmpty()) { + m_allEventsLoaded.insert(eventToAdd->getEventName()); + } + } - return AudioManager::addAudioEvent(eventToAdd); + return AudioManager::addAudioEvent(eventToAdd); } #endif #if defined(RTS_DEBUG) //------------------------------------------------------------------------------------------------- -void MilesAudioManager::audioDebugDisplay(DebugDisplayInterface* dd, void*, FILE* fp) -{ - std::list::iterator it; - - static char buffer[128] = { 0 }; - if (buffer[0] == 0) { - AIL_MSS_version(buffer, 128); - } - - Coord3D lookPos = TheTacticalView->getPosition(); - const Coord3D* mikePos = TheAudio->getListenerPosition(); - Coord3D distanceVector = TheTacticalView->get3DCameraPosition(); - distanceVector.sub(*mikePos); - - Int now = TheGameLogic->getFrame(); - static Int lastCheck = now; - const Int frames = 60; - static Int latency = 0; - static Int worstLatency = 0; - if (lastCheck + frames <= now) - { - latency = AIL_get_timer_highest_delay(); - if (latency > worstLatency) - { - worstLatency = latency; - } - lastCheck = now; - } - - if (dd) - { - dd->printf("Miles Sound System version: %s ", buffer); - dd->printf("Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize()); - dd->printf("Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No")); - dd->printf("3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No")); - dd->printf("Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No")); - dd->printf("Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No")); - dd->printf("Channels Available: "); - dd->printf("%u Sounds ", getNumAvailable2DSamples()); - dd->printf("%u 3D Sounds\n", getNumAvailable3DSamples()); - dd->printf("Volume: "); - dd->printf("Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f)); - dd->printf("3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f)); - dd->printf("Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f)); - dd->printf("Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f)); - dd->printf("Current 3D Provider: %s ", - - TheAudio->getProviderName(m_selectedProvider).str()); - dd->printf("Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str()); - - dd->printf("Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n", - (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z); - dd->printf("Camera distance from microphone: %d -- Zoom Volume: %d%%\n", - (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume() * 100.0f)); - dd->printf("Worst latency: %d -- Current latency: %d\n", worstLatency, latency); - - dd->printf("-----------------------------------------------------------\n"); - dd->printf("Playing Audio\n"); - } - if (fp) - { - fprintf(fp, "Miles Sound System version: %s ", buffer); - fprintf(fp, "Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize()); - fprintf(fp, "Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No")); - fprintf(fp, "3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No")); - fprintf(fp, "Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No")); - fprintf(fp, "Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No")); - fprintf(fp, "Channels Available: "); - fprintf(fp, "%u Sounds ", getNumAvailable2DSamples()); - fprintf(fp, "%u 3D Sounds\n", getNumAvailable3DSamples()); - fprintf(fp, "Volume: "); - fprintf(fp, "Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f)); - fprintf(fp, "3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f)); - fprintf(fp, "Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f)); - fprintf(fp, "Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f)); - fprintf(fp, "Current 3D Provider: %s ", TheAudio->getProviderName(m_selectedProvider).str()); - fprintf(fp, "Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str()); - - fprintf(fp, "Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n", - (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z); - fprintf(fp, "Camera distance from microphone: %d -- Zoom Volume: %d%%\n", - (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume() * 100.0f)); - - fprintf(fp, "-----------------------------------------------------------\n"); - fprintf(fp, "Playing Audio\n"); - } - - PlayingAudio* playing = nullptr; - Int channel; - Int channelCount; - Real volume = 0.0f; - AsciiString filenameNoSlashes; - - const Int maxChannels = 64; - PlayingAudio* playingArray[maxChannels] = { nullptr }; - - // 2-D Sounds - if (dd) - { - dd->printf("-----------------------------------------------------Sounds\n"); - channelCount = TheAudio->getNum2DSamples(); - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - playingArray[(int)AIL_sample_user_data(playing->m_sample, 0)] = playing; - } - - for (Int i = 1; i <= maxChannels && i <= channelCount; ++i) { - playing = playingArray[i]; - if (!playing) { - dd->printf("%d: Silence\n", i); - continue; - } - - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - - dd->printf("%2d: %-20s - (%s) Volume: %d (2D)\n", i, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); - playingArray[i] = nullptr; - } - } - if (fp) - { - fprintf(fp, "-----------------------------------------------------Sounds\n"); - channelCount = TheAudio->getNum2DSamples(); - channel = 1; - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) - { - playing = *it; - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - - fprintf(fp, "%2d: %-20s - (%s) Volume: %d (2D)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); - } - for (int i = channel; i <= channelCount; ++i) - { - fprintf(fp, "%d: Silence\n", i); - } - } - - const Coord3D* microphonePos = TheAudio->getListenerPosition(); - - // Now 3D Sounds - if (dd) - { - dd->printf("--------------------------------------------------3D Sounds\n"); - channelCount = TheAudio->getNum3DSamples(); - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - playingArray[(int)AIL_3D_user_data(playing->m_3DSample, 0)] = playing; - } - - for (Int i = 1; i <= maxChannels && i <= channelCount; ++i) - { - playing = playingArray[i]; - if (!playing) - { - dd->printf("%d: Silence\n", i); - continue; - } - - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - Real dist = -1.0f; - const Coord3D* pos = playing->m_audioEventRTS->getPosition(); - char distStr[32]; - if (pos) - { - Coord3D vector = *microphonePos; - vector.sub(*pos); - dist = vector.length(); - sprintf(distStr, "%d", REAL_TO_INT(dist)); - } - else - { - sprintf(distStr, "???"); - } - char str[32]; - switch (playing->m_audioEventRTS->getOwnerType()) - { - case OT_Positional: - sprintf(str, "(3D)"); - break; - case OT_Object: - sprintf(str, "(3DObj)"); - break; - case OT_Drawable: - sprintf(str, "(3DDraw)"); - break; - case OT_Dead: - sprintf(str, "(3DDead)"); - break; - - } - - dd->printf("%2d: %-20s - (%s) Volume: %d, Dist: %s, %s\n", - i, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume), distStr, str); - playingArray[i] = nullptr; - } - } - if (fp) - { - fprintf(fp, "--------------------------------------------------3D Sounds\n"); - channelCount = TheAudio->getNum3DSamples(); - channel = 1; - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) - { - playing = *it; - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - fprintf(fp, "%2d: %-24s - (%s) Volume: %d \n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); - } - - for (int i = channel; i <= channelCount; ++i) - { - fprintf(fp, "%2d: Silence\n", i); - } - } - - // Now Streams - if (dd) - { - dd->printf("----------------------------------------------------Streams\n"); - channelCount = TheAudio->getNumStreams(); - channel = 1; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - - dd->printf("%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); - } - - for (int i = channel; i <= channelCount; ++i) { - dd->printf("%2d: Silence\n", i); - } - dd->printf("===========================================================\n"); - } - if (fp) - { - fprintf(fp, "----------------------------------------------------Streams\n"); - channelCount = TheAudio->getNumStreams(); - channel = 1; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) - { - playing = *it; - filenameNoSlashes = playing->m_audioEventRTS->getFilename(); - filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; - - // Calculate Sample volume - volume = 100.0f; - volume *= getEffectiveVolume(playing->m_audioEventRTS); - - fprintf(fp, "%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); - } - - for (int i = channel; i <= channelCount; ++i) - { - fprintf(fp, "%2d: Silence\n", i); - } - fprintf(fp, "===========================================================\n"); - } +void MilesAudioManager::audioDebugDisplay(DebugDisplayInterface *dd, void *, FILE *fp ) +{ + std::list::iterator it; + + static char buffer[128] = { 0 }; + if (buffer[0] == 0) { + AIL_MSS_version(buffer, 128); + } + + Coord3D lookPos = TheTacticalView->getPosition(); + const Coord3D *mikePos = TheAudio->getListenerPosition(); + Coord3D distanceVector = TheTacticalView->get3DCameraPosition(); + distanceVector.sub( *mikePos ); + + Int now = TheGameLogic->getFrame(); + static Int lastCheck = now; + const Int frames = 60; + static Int latency = 0; + static Int worstLatency = 0; + if( lastCheck + frames <= now ) + { + latency = AIL_get_timer_highest_delay(); + if( latency > worstLatency ) + { + worstLatency = latency; + } + lastCheck = now; + } + + if( dd ) + { + dd->printf("Miles Sound System version: %s ", buffer); + dd->printf("Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize()); + dd->printf("Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No")); + dd->printf("3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No")); + dd->printf("Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No")); + dd->printf("Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No")); + dd->printf("Channels Available: "); + dd->printf("%u Sounds ", getNumAvailable2DSamples()); + dd->printf("%u 3D Sounds\n", getNumAvailable3DSamples()); + dd->printf("Volume: "); + dd->printf("Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f)); + dd->printf("3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f)); + dd->printf("Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f)); + dd->printf("Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f)); + dd->printf("Current 3D Provider: %s ", + + TheAudio->getProviderName(m_selectedProvider).str()); + dd->printf("Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str()); + + dd->printf( "Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n", + (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z ); + dd->printf( "Camera distance from microphone: %d -- Zoom Volume: %d%%\n", + (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume()*100.0f) ); + dd->printf( "Worst latency: %d -- Current latency: %d\n", worstLatency, latency ); + + dd->printf("-----------------------------------------------------------\n"); + dd->printf("Playing Audio\n"); + } + if( fp ) + { + fprintf( fp, "Miles Sound System version: %s ", buffer ); + fprintf( fp, "Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize() ); + fprintf( fp, "Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No") ); + fprintf( fp, "3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No") ); + fprintf( fp, "Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No") ); + fprintf( fp, "Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No") ); + fprintf( fp, "Channels Available: " ); + fprintf( fp, "%u Sounds ", getNumAvailable2DSamples() ); + fprintf( fp, "%u 3D Sounds\n", getNumAvailable3DSamples() ); + fprintf( fp, "Volume: "); + fprintf( fp, "Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f) ); + fprintf( fp, "3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f) ); + fprintf( fp, "Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f) ); + fprintf( fp, "Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f) ); + fprintf( fp, "Current 3D Provider: %s ", TheAudio->getProviderName(m_selectedProvider).str()); + fprintf( fp, "Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str()); + + fprintf( fp, "Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n", + (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z ); + fprintf( fp, "Camera distance from microphone: %d -- Zoom Volume: %d%%\n", + (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume()*100.0f) ); + + fprintf( fp, "-----------------------------------------------------------\n" ); + fprintf( fp, "Playing Audio\n" ); + } + + PlayingAudio *playing = nullptr; + Int channel; + Int channelCount; + Real volume = 0.0f; + AsciiString filenameNoSlashes; + + const Int maxChannels = 64; + PlayingAudio *playingArray[maxChannels] = { nullptr }; + + // 2-D Sounds + if( dd ) + { + dd->printf("-----------------------------------------------------Sounds\n"); + channelCount = TheAudio->getNum2DSamples(); + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + playingArray[(int)AIL_sample_user_data(playing->m_sample, 0)] = playing; + } + + for (Int i = 1; i <= maxChannels && i <= channelCount; ++i) { + playing = playingArray[i]; + if (!playing) { + dd->printf("%2d: Silence\n", i); + continue; + } + + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume(event); + + dd->printf("%2d: %-20s - (%s) Volume: %d (2D)\n", i, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); + playingArray[i] = nullptr; + } + } + if( fp ) + { + fprintf( fp, "-----------------------------------------------------Sounds\n" ); + channelCount = TheAudio->getNum2DSamples(); + channel = 1; + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) + { + playing = *it; + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind( '\\' ) + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume( event ); + + fprintf( fp, "%2d: %-20s - (%s) Volume: %d (2D)\n", channel++, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) ); + } + for( int i = channel; i <= channelCount; ++i ) + { + fprintf( fp, "%2d: Silence\n", i ); + } + } + + const Coord3D *microphonePos = TheAudio->getListenerPosition(); + + // Now 3D Sounds + if( dd ) + { + dd->printf("--------------------------------------------------3D Sounds\n"); + channelCount = TheAudio->getNum3DSamples(); + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + playingArray[(int)AIL_3D_user_data(playing->m_3DSample, 0)] = playing; + } + + for (Int i = 1; i <= maxChannels && i <= channelCount; ++i) + { + playing = playingArray[i]; + if (!playing) + { + dd->printf("%2d: Silence\n", i); + continue; + } + + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume(event); + Real dist = -1.0f; + const Coord3D *pos = event->getPosition(); + char distStr[32]; + if( pos ) + { + Coord3D vector = *microphonePos; + vector.sub( *pos ); + dist = vector.length(); + sprintf( distStr, "%d", REAL_TO_INT( dist ) ); + } + else + { + sprintf( distStr, "???" ); + } + char str[32]; + switch( event->getOwnerType() ) + { + case OT_Positional: + sprintf( str, "(3D)" ); + break; + case OT_Object: + sprintf( str, "(3DObj)" ); + break; + case OT_Drawable: + sprintf( str, "(3DDraw)" ); + break; + case OT_Dead: + sprintf( str, "(3DDead)" ); + break; + + } + + dd->printf("%2d: %-20s - (%s) Volume: %d, Dist: %s, %s\n", + i, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume), distStr, str ); + playingArray[i] = nullptr; + } + } + if( fp ) + { + fprintf( fp, "--------------------------------------------------3D Sounds\n" ); + channelCount = TheAudio->getNum3DSamples(); + channel = 1; + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) + { + playing = *it; + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume( event ); + fprintf( fp, "%2d: %-24s - (%s) Volume: %d \n", channel++, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) ); + } + + for( int i = channel; i <= channelCount; ++i ) + { + fprintf( fp, "%2d: Silence\n", i ); + } + } + + // Now Streams + if( dd ) + { + dd->printf("----------------------------------------------------Streams\n"); + channelCount = TheAudio->getNumStreams(); + channel = 1; + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume(event); + + dd->printf("%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume)); + } + + for ( int i = channel; i <= channelCount; ++i) { + dd->printf("%2d: Silence\n", i); + } + dd->printf("===========================================================\n"); + } + if( fp ) + { + fprintf( fp, "----------------------------------------------------Streams\n" ); + channelCount = TheAudio->getNumStreams(); + channel = 1; + for( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) + { + playing = *it; + AudioEventRTS *event = playing->m_audioEventRTS.Peek(); + filenameNoSlashes = event->getFilename(); + filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1; + + // Calculate Sample volume + volume = 100.0f; + volume *= getEffectiveVolume(event); + + fprintf( fp, "%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, event->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) ); + } + + for( int i = channel; i <= channelCount; ++i ) + { + fprintf( fp, "%2d: Silence\n", i ); + } + fprintf( fp, "===========================================================\n" ); + } } #endif //------------------------------------------------------------------------------------------------- void MilesAudioManager::init() { - AudioManager::init(); + AudioManager::init(); #ifdef INTENSE_DEBUG - DEBUG_LOG(("Sound has temporarily been disabled in debug builds only. jkmcd")); - // for now, RTS_DEBUG builds only should have no sound. ask jkmcd or srj about this. - return; + DEBUG_LOG(("Sound has temporarily been disabled in debug builds only. jkmcd")); + // for now, RTS_DEBUG builds only should have no sound. ask jkmcd or srj about this. + return; #endif - // We should now know how many samples we want to load - openDevice(); - m_audioCache->setMaxSize(getAudioSettings()->m_maxCacheSize); + // We should now know how many samples we want to load + openDevice(); + m_audioCache->setMaxSize(getAudioSettings()->m_maxCacheSize); - // Now, set the file callbacks to load the streams from Biggie files - AIL_set_file_callbacks(streamingFileOpen, streamingFileClose, streamingFileSeek, streamingFileRead); + // Now, set the file callbacks to load the streams from Biggie files + AIL_set_file_callbacks(streamingFileOpen, streamingFileClose, streamingFileSeek, streamingFileRead); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::postProcessLoad() { - AudioManager::postProcessLoad(); + AudioManager::postProcessLoad(); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::reset() { #if defined(RTS_DEBUG) - dumpAllAssetsUsed(); - m_allEventsLoaded.clear(); + dumpAllAssetsUsed(); + m_allEventsLoaded.clear(); #endif - AudioManager::reset(); - stopAllAudioImmediately(); - removeAllAudioRequests(); - // This must come after stopAllAudioImmediately() and removeAllAudioRequests(), to ensure that - // sounds pointing to the temporary AudioEventInfo handles are deleted before their info is deleted - removeLevelSpecificAudioEventInfos(); + AudioManager::reset(); + stopAllAudioImmediately(); + removeAllAudioRequests(); + // This must come after stopAllAudioImmediately() and removeAllAudioRequests(), to ensure that + // sounds pointing to the temporary AudioEventInfo handles are deleted before their info is deleted + removeLevelSpecificAudioEventInfos(); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::update() { - AudioManager::update(); - setDeviceListenerPosition(); - processRequestList(); - processPlayingList(); - processFadingList(); -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::stopAudio(AudioAffect which) -{ - // All we really need to do is: - // 1) Remove the EOS callback. - // 2) Stop the sample, (so that when we later unload it, bad stuff doesn't happen) - // 3) Set the status to stopped, so that when we next process the playing list, we will - // correctly clean up the sample. - - std::list::iterator it; - - PlayingAudio* playing = nullptr; - if (BitIsSet(which, AudioAffect_Sound)) { - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - stopPlayingAudio(playing); - } - } - - if (BitIsSet(which, AudioAffect_Sound3D)) { - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - stopPlayingAudio(playing); - } - } - - if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - if (!BitIsSet(which, AudioAffect_Music)) { - continue; - } - } - else { - if (!BitIsSet(which, AudioAffect_Speech)) { - continue; - } - } - stopPlayingAudio(playing); - } - } -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::pauseAudio(AudioAffect which) -{ - std::list::iterator it; - - PlayingAudio* playing = nullptr; - if (BitIsSet(which, AudioAffect_Sound)) { - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); - AIL_stop_sample(playing->m_sample); - } - } - - if (BitIsSet(which, AudioAffect_Sound3D)) { - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - DEBUG_ASSERTCRASH(playing->m_sample, ("3D Sample is not expected to be null")); - AIL_stop_3D_sample(playing->m_3DSample); - } - } - - if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - if (!BitIsSet(which, AudioAffect_Music)) { - continue; - } - } - else { - if (!BitIsSet(which, AudioAffect_Speech)) { - continue; - } - } - DEBUG_ASSERTCRASH(playing->m_sample, ("Stream is not expected to be null")); - AIL_pause_stream(playing->m_stream, 1); - } - } - - //Get rid of PLAY audio requests when pausing audio. - std::list::iterator ait; - for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ) - { - AudioRequest* req = (*ait); - if (req->m_request == AR_Play) - { - deleteInstance(req); - ait = m_audioRequests.erase(ait); - } - else - { - ait++; - } - } -} - - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::resumeAudio(AudioAffect which) -{ - std::list::iterator it; - - PlayingAudio* playing = nullptr; - if (BitIsSet(which, AudioAffect_Sound)) { - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); - AIL_resume_sample(playing->m_sample); - } - } - - if (BitIsSet(which, AudioAffect_Sound3D)) { - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); - AIL_resume_3D_sample(playing->m_3DSample); - } - } - - if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - if (!BitIsSet(which, AudioAffect_Music)) { - continue; - } - } - else { - if (!BitIsSet(which, AudioAffect_Speech)) { - continue; - } - } - DEBUG_ASSERTCRASH(playing->m_stream, ("Stream is not expected to be null")); - AIL_pause_stream(playing->m_stream, 0); - } - } -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::pauseAmbient(Bool shouldPause) -{ - -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::playAudioEvent(AudioRequest* req) -{ - DEBUG_ASSERTCRASH(req->m_usePendingEvent && req->m_pendingEvent, ("audio request was expected to contain a valid audio event")); - - AudioEventRTS* event = req->m_pendingEvent; + AudioManager::update(); + setDeviceListenerPosition(); + processRequestList(); + processPlayingList(); + processFadingList(); +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::stopAudio( AudioAffect which ) +{ + // All we really need to do is: + // 1) Remove the EOS callback. + // 2) Stop the sample, (so that when we later unload it, bad stuff doesn't happen) + // 3) Set the status to stopped, so that when we next process the playing list, we will + // correctly clean up the sample. + + std::list::iterator it; + + PlayingAudio *playing = nullptr; + if (BitIsSet(which, AudioAffect_Sound)) { + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + stopPlayingAudio(playing); + } + } + + if (BitIsSet(which, AudioAffect_Sound3D)) { + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + stopPlayingAudio(playing); + } + } + + if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + if (!BitIsSet(which, AudioAffect_Music)) { + continue; + } + } else { + if (!BitIsSet(which, AudioAffect_Speech)) { + continue; + } + } + stopPlayingAudio(playing); + } + } +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::pauseAudio( AudioAffect which ) +{ + std::list::iterator it; + + PlayingAudio *playing = nullptr; + if (BitIsSet(which, AudioAffect_Sound)) { + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); + AIL_stop_sample(playing->m_sample); + } + } + + if (BitIsSet(which, AudioAffect_Sound3D)) { + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); + AIL_stop_3D_sample(playing->m_3DSample); + } + } + + if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + if (!BitIsSet(which, AudioAffect_Music)) { + continue; + } + } else { + if (!BitIsSet(which, AudioAffect_Speech)) { + continue; + } + } + DEBUG_ASSERTCRASH(playing->m_stream, ("Stream is not expected to be null")); + AIL_pause_stream(playing->m_stream, 1); + } + } + + //Get rid of PLAY audio requests when pausing audio. + std::list::iterator ait; + for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ) + { + AudioRequest *req = (*ait); + if( req->m_request == AR_Play ) + { + deleteInstance(req); + ait = m_audioRequests.erase(ait); + } + else + { + ait++; + } + } +} + + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::resumeAudio( AudioAffect which ) +{ + std::list::iterator it; + + PlayingAudio *playing = nullptr; + if (BitIsSet(which, AudioAffect_Sound)) { + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); + AIL_resume_sample(playing->m_sample); + } + } + + if (BitIsSet(which, AudioAffect_Sound3D)) { + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); + AIL_resume_3D_sample(playing->m_3DSample); + } + } + + if (BitIsSet(which, AudioAffect_Speech | AudioAffect_Music)) { + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + if (!BitIsSet(which, AudioAffect_Music)) { + continue; + } + } else { + if (!BitIsSet(which, AudioAffect_Speech)) { + continue; + } + } + DEBUG_ASSERTCRASH(playing->m_stream, ("Stream is not expected to be null")); + AIL_pause_stream(playing->m_stream, 0); + } + } +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::pauseAmbient( Bool shouldPause ) +{ + +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::playAudioEvent( AudioRequest* req ) +{ + DEBUG_ASSERTCRASH(req->m_pendingEvent != nullptr, ("audio request was expected to contain a valid audio event")); + + AudioEventRTS* event = req->m_pendingEvent.Peek(); #ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG(("MILES (%d) - Processing play request: %d (%s)", TheGameLogic->getFrame(), event->getPlayingHandle(), event->getEventName().str())); + DEBUG_LOG(("MILES (%d) - Processing play request: %d (%s)", TheGameLogic->getFrame(), event->getPlayingHandle(), event->getEventName().str())); #endif - const AudioEventInfo* info = event->getAudioEventInfo(); - if (!info) { - return; - } - - std::list::iterator it; - PlayingAudio* playing = nullptr; - - AudioHandle handleToKill = event->getHandleToKill(); - - AsciiString fileToPlay = event->getFilename(); - PlayingAudio* audio = allocatePlayingAudio(); - switch (info->m_soundType) - { - case AT_Music: - case AT_Streaming: - { + const AudioEventInfo *info = event->getAudioEventInfo(); + if (!info) { + return; + } + + std::list::iterator it; + PlayingAudio *playing = nullptr; + + AudioHandle handleToKill = event->getHandleToKill(); + + AsciiString fileToPlay = event->getFilename(); + PlayingAudio *newPlaying = allocatePlayingAudio(); + newPlaying->m_requestStop = req->m_requestStop; + + switch(info->m_soundType) + { + case AT_Music: + case AT_Streaming: + { + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG(("- Stream")); + #endif + + if ((info->m_soundType == AT_Streaming) && event->getUninterruptible()) { + stopAllSpeech(); + } + + Bool foundSoundToReplace = false; + if (handleToKill) { + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = (*it); + + if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill) + { + //Release this streaming channel immediately because we are going to play another sound in it's place. + stopPlayingAudio(playing); + foundSoundToReplace = true; + break; + } + } + } + + HSTREAM stream; + if (!handleToKill || foundSoundToReplace) { + stream = AIL_open_stream(m_digitalHandle, fileToPlay.str(), 0); + } else { + stream = nullptr; + } + + // Put this on here, so that the audio event RTS will be cleaned up regardless. + newPlaying->m_audioEventRTS = req->m_pendingEvent; + newPlaying->m_stream = stream; + newPlaying->m_type = PAT_Stream; + + if (stream) { + if ((info->m_soundType == AT_Streaming) && event->getUninterruptible()) { + setDisallowSpeech(TRUE); + } + AIL_set_stream_volume_pan(stream, getEffectiveVolume(event), 0.5f); + playStream(event, stream); + + CriticalSectionClass::LockClass lock(m_playingStreamsCS); + m_playingStreams.push_back(newPlaying); + newPlaying = nullptr; + } + break; + } + + case AT_SoundEffect: + { + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG(("- Sound")); + #endif + + + if (event->isPositionalAudio()) { + // Sounds that are non-global are positional 3-D sounds. Deal with them accordingly + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" Positional")); + #endif + Bool foundSoundToReplace = false; + if (handleToKill) + { + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = (*it); + + if( playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill ) + { + //Release this 3D sound channel immediately because we are going to play another sound in it's place. + stopPlayingAudio(playing); + foundSoundToReplace = true; + break; + } + } + } + + H3DSAMPLE sample3D; + if( !handleToKill || foundSoundToReplace ) + { + sample3D = getAvailable3DSample( event ); + if( !sample3D ) + { + //If we don't have an available sample, kill the lowest priority assuming we have one that is lower + //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound + //that wants to kill a handle to replace it, it's possible that another request already killed it, + //in which case we need to attempt to find another sound to kill. + if( killLowestPrioritySoundImmediately( event ) ) + { + sample3D = getAvailable3DSample( event ); + } + } + } + else + { + sample3D = nullptr; + } + // Push it onto the list of playing things + newPlaying->m_audioEventRTS = req->m_pendingEvent; + newPlaying->m_3DSample = sample3D; + newPlaying->m_file = nullptr; + newPlaying->m_type = PAT_3DSample; + + if (sample3D) { + newPlaying->m_file = playSample3D(event, sample3D); + } + + if( !newPlaying->m_file ) + { + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" Killed (no handles available)")); + #endif + } + else + { + CriticalSectionClass::LockClass lock(m_playing3DSoundsCS); + m_playing3DSounds.push_back(newPlaying); + newPlaying = nullptr; + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" Playing.")); + #endif + } + } + else + { + // UI sounds are always 2-D. All other sounds should be Positional + // Unit acknowledgment, etc, falls into the UI category of sound. + Bool foundSoundToReplace = false; + if (handleToKill) { + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = (*it); + + if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill) + { + //Release this 2D sound channel immediately because we are going to play another sound in it's place. + stopPlayingAudio(playing); + foundSoundToReplace = true; + break; + } + } + } + + HSAMPLE sample; + if( !handleToKill || foundSoundToReplace ) + { + sample = getAvailable2DSample(event); + if( !sample ) + { + //If we don't have an available sample, kill the lowest priority assuming we have one that is lower + //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound + //that wants to kill a handle to replace it, it's possible that another request already killed it, + //in which case we need to attempt to find another sound to kill. + if( killLowestPrioritySoundImmediately( event ) ) + { + sample = getAvailable2DSample( event ); + } + } + } + else + { + sample = nullptr; + } + + // Push it onto the list of playing things + newPlaying->m_audioEventRTS = req->m_pendingEvent; + newPlaying->m_sample = sample; + newPlaying->m_file = nullptr; + newPlaying->m_type = PAT_Sample; + + if (sample) { + newPlaying->m_file = playSample(event, sample); + } + + if (!newPlaying->m_file) { + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" Killed (no handles available)")); + #endif + } else { + CriticalSectionClass::LockClass lock(m_playingSoundsCS); + m_playingSounds.push_back(newPlaying); + newPlaying = nullptr; + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" Playing.")); + #endif + } + } + break; + } + } + + // If we were able to successfully play audio, then we set it to null above. (And it will be freed + // later. However, if audio is non-null at this point, then it must be freed. + if (newPlaying) { + stopPlayingAudio(newPlaying); + releasePlayingAudio(newPlaying); + } +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::stopAudioEvent( AudioHandle handle ) +{ #ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG(("- Stream")); + DEBUG_LOG(("MILES (%d) - Processing stop request: %d", TheGameLogic->getFrame(), handle)); #endif - if ((info->m_soundType == AT_Streaming) && event->getUninterruptible()) { - stopAllSpeech(); - } - - Bool foundSoundToReplace = false; - if (handleToKill) { - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = (*it); - - if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill) - { - //Release this streaming channel immediately because we are going to play another sound in it's place. - stopPlayingAudio(playing); - foundSoundToReplace = true; - break; - } - } - } - - HSTREAM stream; - if (!handleToKill || foundSoundToReplace) { - stream = AIL_open_stream(m_digitalHandle, fileToPlay.str(), 0); - } - else { - stream = nullptr; - } - - // Put this on here, so that the audio event RTS will be cleaned up regardless. - audio->m_audioEventRTS = event = req->releasePendingEvent(); - audio->m_stream = stream; - audio->m_type = PAT_Stream; - - if (stream) { - if ((info->m_soundType == AT_Streaming) && event->getUninterruptible()) { - setDisallowSpeech(TRUE); - } - AIL_set_stream_volume_pan(stream, getEffectiveVolume(event), 0.5f); - playStream(event, stream); - - CriticalSectionClass::LockClass lock(m_playingStreamsCS); - m_playingStreams.push_back(audio); - audio = nullptr; - } - break; - } - - case AT_SoundEffect: - { -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG(("- Sound")); -#endif + std::list::iterator it; + if ( handle == AHSV_StopTheMusic || handle == AHSV_StopTheMusicFade ) { + // for music, find and stop the currently playing music stream(s). + for ( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) { + PlayingAudio *playing = (*it); + + if( playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music ) + { + if( handle == AHSV_StopTheMusicFade ) + { + fadePlayingAudio(playing); + } + else + { + stopPlayingAudio(playing); + } + } + } + return; + } + + // Look for it in the request list. + { + std::list::iterator it; + for( it = m_audioRequests.begin(); it != m_audioRequests.end(); it++ ) + { + AudioRequest *req = (*it); + if( req->m_pendingEvent && req->m_pendingEvent->getPlayingHandle() == handle ) + { + if (req->m_pendingEvent->getAudioEventInfo()->m_soundType == AT_SoundEffect) + { + req->m_requestStop = true; + } + else + { + deleteInstance(req); + m_audioRequests.erase(it); + } + return; + } + } + } + + for ( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) { + PlayingAudio *playing = (*it); + + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + stopPlayingAudio(playing); + return; + } + } + + for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + PlayingAudio *playing = (*it); + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + playing->m_requestStop = true; + return; + } + } - if (event->isPositionalAudio()) { - // Sounds that are non-global are positional 3-D sounds. Deal with them accordingly -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" Positional")); -#endif - Bool foundSoundToReplace = false; - if (handleToKill) - { - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = (*it); - - if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill) - { - //Release this 3D sound channel immediately because we are going to play another sound in it's place. - stopPlayingAudio(playing); - foundSoundToReplace = true; - break; - } - } - } - - H3DSAMPLE sample3D; - if (!handleToKill || foundSoundToReplace) - { - sample3D = getAvailable3DSample(event); - if (!sample3D) - { - //If we don't have an available sample, kill the lowest priority assuming we have one that is lower - //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound - //that wants to kill a handle to replace it, it's possible that another request already killed it, - //in which case we need to attempt to find another sound to kill. - if (killLowestPrioritySoundImmediately(event)) - { - sample3D = getAvailable3DSample(event); - } - } - } - else - { - sample3D = nullptr; - } - // Push it onto the list of playing things - audio->m_audioEventRTS = event = req->releasePendingEvent(); - audio->m_3DSample = sample3D; - audio->m_file = nullptr; - audio->m_type = PAT_3DSample; - - if (sample3D) { - audio->m_file = playSample3D(event, sample3D); - } - - if (!audio->m_file) - { -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" Killed (no handles available)")); -#endif - } - else - { - CriticalSectionClass::LockClass lock(m_playing3DSoundsCS); - m_playing3DSounds.push_back(audio); - audio = nullptr; -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" Playing.")); -#endif - } - } - else - { - // UI sounds are always 2-D. All other sounds should be Positional - // Unit acknowledgment, etc, falls into the UI category of sound. - Bool foundSoundToReplace = false; - if (handleToKill) { - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = (*it); - - if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill) - { - //Release this 2D sound channel immediately because we are going to play another sound in it's place. - stopPlayingAudio(playing); - foundSoundToReplace = true; - break; - } - } - } - - HSAMPLE sample; - if (!handleToKill || foundSoundToReplace) - { - sample = getAvailable2DSample(event); - if (!sample) - { - //If we don't have an available sample, kill the lowest priority assuming we have one that is lower - //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound - //that wants to kill a handle to replace it, it's possible that another request already killed it, - //in which case we need to attempt to find another sound to kill. - if (killLowestPrioritySoundImmediately(event)) - { - sample = getAvailable2DSample(event); - } - } - } - else - { - sample = nullptr; - } - - // Push it onto the list of playing things - audio->m_audioEventRTS = event = req->releasePendingEvent(); - audio->m_sample = sample; - audio->m_file = nullptr; - audio->m_type = PAT_Sample; - - if (sample) { - audio->m_file = playSample(event, sample); - } - - if (!audio->m_file) { -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" Killed (no handles available)")); -#endif - } - else { - CriticalSectionClass::LockClass lock(m_playingSoundsCS); - m_playingSounds.push_back(audio); - audio = nullptr; -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" Playing.")); -#endif - } - } - break; - } - } + for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + PlayingAudio *playing = (*it); + + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + #ifdef INTENSIVE_AUDIO_DEBUG + DEBUG_LOG((" (%s)", playing->m_audioEventRTS->getEventName())); + #endif + playing->m_requestStop = true; + return; + } + } +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::killAudioEventImmediately( AudioHandle audioEvent ) +{ + //First look for it in the request list. + std::list::iterator ait; + for( ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ait++ ) + { + AudioRequest *req = (*ait); + if( req->m_pendingEvent && req->m_pendingEvent->getPlayingHandle() == audioEvent ) + { + deleteInstance(req); + m_audioRequests.erase(ait); + return; + } + } + + //Look for matching 3D sound to kill + std::list::iterator it; + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); it++ ) + { + PlayingAudio *playing = (*it); + + if( playing->m_audioEventRTS->getPlayingHandle() == audioEvent ) + { + stopPlayingAudio(playing); + return; + } + } + + //Look for matching 2D sound to kill + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); it++ ) + { + PlayingAudio *playing = (*it); + + if( playing->m_audioEventRTS->getPlayingHandle() == audioEvent ) + { + stopPlayingAudio(playing); + return; + } + } + + //Look for matching steaming sound to kill + for( it = m_playingStreams.begin(); it != m_playingStreams.end(); it++ ) + { + PlayingAudio *playing = (*it); - // If we were able to successfully play audio, then we set it to null above. (And it will be freed - // later. However, if audio is non-null at this point, then it must be freed. - if (audio) { - stopPlayingAudio(audio); - releasePlayingAudio(audio); - } + if( playing->m_audioEventRTS->getPlayingHandle() == audioEvent ) + { + stopPlayingAudio(playing); + return; + } + } } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::stopAudioEvent(AudioHandle handle) +void MilesAudioManager::pauseAudioEvent( AudioHandle handle ) { -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG(("MILES (%d) - Processing stop request: %d", TheGameLogic->getFrame(), handle)); -#endif - - std::list::iterator it; - if (handle == AHSV_StopTheMusic || handle == AHSV_StopTheMusicFade) { - // for music, find and stop the currently playing music stream(s). - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) - { - if (handle == AHSV_StopTheMusicFade) - { - fadePlayingAudio(audio); - } - else - { - stopPlayingAudio(audio); - } - } - } - return; - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == handle) { - stopPlayingAudio(audio); - break; - } - } - - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == handle) { - stopPlayingAudio(audio); - break; - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == handle) { -#ifdef INTENSIVE_AUDIO_DEBUG - DEBUG_LOG((" (%s)", audio->m_audioEventRTS->getEventName())); -#endif - stopPlayingAudio(audio); - break; - } - } + // pause audio } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::killAudioEventImmediately(AudioHandle audioEvent) +void *MilesAudioManager::loadFileForRead( AudioEventRTS *eventToLoadFrom ) { - //First look for it in the request list. - std::list::iterator ait; - for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ait++) - { - AudioRequest* req = (*ait); - if (req->m_usePendingEvent && req->m_pendingEvent->getPlayingHandle() == audioEvent) - { - deleteInstance(req); - ait = m_audioRequests.erase(ait); - return; - } - } - - //Look for matching 3D sound to kill - std::list::iterator it; - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); it++) - { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == audioEvent) - { - stopPlayingAudio(audio); - return; - } - } - - //Look for matching 2D sound to kill - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); it++) - { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == audioEvent) - { - stopPlayingAudio(audio); - return; - } - } - - //Look for matching steaming sound to kill - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); it++) - { - PlayingAudio* audio = (*it); - - if (audio->m_audioEventRTS->getPlayingHandle() == audioEvent) - { - stopPlayingAudio(audio); - return; - } - } - + return m_audioCache->openFile(eventToLoadFrom); } - //------------------------------------------------------------------------------------------------- -void MilesAudioManager::pauseAudioEvent(AudioHandle handle) +void MilesAudioManager::closeFile( void *fileRead ) { - // pause audio + m_audioCache->closeFile(fileRead); } + //------------------------------------------------------------------------------------------------- -void* MilesAudioManager::loadFileForRead(AudioEventRTS* eventToLoadFrom) +PlayingAudio *MilesAudioManager::allocatePlayingAudio() { - return m_audioCache->openFile(eventToLoadFrom); + return NEW PlayingAudio; // poolify } + //------------------------------------------------------------------------------------------------- -void MilesAudioManager::closeFile(void* fileRead) +void MilesAudioManager::releaseMilesHandles( PlayingAudio *playing ) { - m_audioCache->closeFile(fileRead); + switch (playing->m_type) + { + case PAT_Sample: + { + if (playing->m_sample) { + AIL_register_EOS_callback(playing->m_sample, nullptr); + AIL_stop_sample(playing->m_sample); + m_availableSamples.push_back(playing->m_sample); + playing->m_sample = nullptr; + } + break; + } + case PAT_3DSample: + { + if (playing->m_3DSample) { + AIL_register_3D_EOS_callback(playing->m_3DSample, nullptr); + AIL_stop_3D_sample(playing->m_3DSample); + m_available3DSamples.push_back(playing->m_3DSample); + playing->m_3DSample = nullptr; + } + break; + } + case PAT_Stream: + { + if (playing->m_stream) { + AIL_register_stream_callback(playing->m_stream, nullptr); + AIL_close_stream(playing->m_stream); + playing->m_stream = nullptr; + } + break; + } + } + playing->m_type = PAT_INVALID; } - //------------------------------------------------------------------------------------------------- -PlayingAudio* MilesAudioManager::allocatePlayingAudio() +void MilesAudioManager::releasePlayingAudio( PlayingAudio *playing ) { - return NEW PlayingAudio; // poolify -} + DEBUG_ASSERTCRASH(playing->m_status == PS_Stopped, ("PlayingAudio must be stopped by now")); + DEBUG_ASSERTCRASH(playing->m_type == PAT_INVALID, ("PlayingAudio must be invalidated by now")); + if (playing->m_file) { + closeFile(playing->m_file); + playing->m_file = nullptr; + } + + delete playing; +} //------------------------------------------------------------------------------------------------- -void MilesAudioManager::releaseMilesHandles(PlayingAudio* release) +void MilesAudioManager::stopPlayingAudio( PlayingAudio *playing ) { - switch (release->m_type) - { - case PAT_Sample: - { - if (release->m_sample) { - AIL_register_EOS_callback(release->m_sample, nullptr); - AIL_stop_sample(release->m_sample); - m_availableSamples.push_back(release->m_sample); - release->m_sample = nullptr; - } - break; - } - case PAT_3DSample: - { - if (release->m_3DSample) { - AIL_register_3D_EOS_callback(release->m_3DSample, nullptr); - AIL_stop_3D_sample(release->m_3DSample); - m_available3DSamples.push_back(release->m_3DSample); - release->m_3DSample = nullptr; - } - break; - } - case PAT_Stream: - { - if (release->m_stream) { - AIL_register_stream_callback(release->m_stream, nullptr); - AIL_close_stream(release->m_stream); - release->m_stream = nullptr; - } - break; - } - } - release->m_type = PAT_INVALID; + // Advance from Playing to Stopping + InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); + // Advance from Stopping to Stopped + const long prevStatus = InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopped, PS_Stopping); + if (prevStatus != PS_Stopping) { + return; + } + releaseMilesHandles(playing); + playing->m_rerequestOnNextUpdate = false; } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::releasePlayingAudio(PlayingAudio* release) +void MilesAudioManager::rerequestPlayingAudio( PlayingAudio *playing ) { - DEBUG_ASSERTCRASH(release->m_status == PS_Stopped, ("PlayingAudio must be stopped by now")); - DEBUG_ASSERTCRASH(release->m_type == PAT_INVALID, ("PlayingAudio must be invalidated by now")); - - if (release->m_file) { - closeFile(release->m_file); - release->m_file = nullptr; - } - - if (release->m_cleanupAudioEventRTS) { - releaseAudioEventRTS(release->m_audioEventRTS); - } - - delete release; + AudioRequest *req = allocateAudioRequest(); + req->m_pendingEvent = playing->m_audioEventRTS; + req->m_requiresCheckForSample = true; + req->m_requestStop = playing->m_requestStop; + appendAudioRequest(req); } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::stopPlayingAudio(PlayingAudio* release) +void MilesAudioManager::rerequestPlayingAudioWhenSignalled( PlayingAudio *playing ) { - // Advance from Playing to Stopping - InterlockedCompareExchange(reinterpret_cast(&release->m_status), PS_Stopping, PS_Playing); - // Advance from Stopping to Stopped - const long prevStatus = InterlockedCompareExchange(reinterpret_cast(&release->m_status), PS_Stopped, PS_Stopping); - if (prevStatus != PS_Stopping) { - return; - } - releaseMilesHandles(release); + if (playing->m_rerequestOnNextUpdate) { + rerequestPlayingAudio(playing); + playing->m_rerequestOnNextUpdate = false; + } } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::fadePlayingAudio(PlayingAudio* playing) +void MilesAudioManager::fadePlayingAudio( PlayingAudio *playing ) { - playing->m_fade = true; + playing->m_fade = true; } //------------------------------------------------------------------------------------------------- -PlayingAudio* MilesAudioManager::findActiveMusic(const AsciiString* trackName) +PlayingAudio *MilesAudioManager::findActiveMusic( const AsciiString* trackName ) { - std::list::const_iterator it; - PlayingAudio* playing; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_status != PS_Playing) { - continue; - } - if (playing->m_fade) { - continue; - } - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType != AT_Music) { - continue; - } - if (trackName && *trackName != playing->m_audioEventRTS->getEventName()) { - continue; - } - return playing; - } - return nullptr; + std::list::const_iterator it; + PlayingAudio *playing; + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + if (playing->m_fade) { + continue; + } + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType != AT_Music) { + continue; + } + if (trackName && *trackName != playing->m_audioEventRTS->getEventName()) { + continue; + } + return playing; + } + return nullptr; } //------------------------------------------------------------------------------------------------- -const PlayingAudio* MilesAudioManager::findActiveMusic(const AsciiString* trackName) const +const PlayingAudio *MilesAudioManager::findActiveMusic( const AsciiString* trackName ) const { - return const_cast(this)->findActiveMusic(trackName); + return const_cast(this)->findActiveMusic(trackName); } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::releasePlayingAudioInListIfStopped(std::list& list, CriticalSectionClass& cs) +void MilesAudioManager::releasePlayingAudioInListIfStopped(std::list &list, CriticalSectionClass &cs) { - std::list::iterator it; - PlayingAudio* playing; - CriticalSectionClass::LockClass lock(cs); + std::list::iterator it; + PlayingAudio *playing; + CriticalSectionClass::LockClass lock(cs); - for (it = list.begin(); it != list.end(); ) - { - playing = (*it); + for (it = list.begin(); it != list.end(); ) + { + playing = (*it); - if (playing->m_status == PS_Stopped) - { - releasePlayingAudio(playing); - it = list.erase(it); - continue; - } + if (playing->m_status == PS_Stopped) + { + releasePlayingAudio(playing); + it = list.erase(it); + continue; + } - ++it; - } + ++it; + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::stopAllAudioImmediately() { - std::list::iterator it; - PlayingAudio* playing; + std::list::iterator it; + PlayingAudio *playing; - // - // Stop audio without locking. Calls into Miles. - // - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = (*it); - stopPlayingAudio(playing); - } + // + // Stop audio without locking. Calls into Miles. + // + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = (*it); + stopPlayingAudio(playing); + } - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = (*it); - stopPlayingAudio(playing); - } + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = (*it); + stopPlayingAudio(playing); + } - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = (*it); - stopPlayingAudio(playing); - } + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = (*it); + stopPlayingAudio(playing); + } - for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { - playing = (*it); - stopPlayingAudio(playing); - } + for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { + playing = (*it); + stopPlayingAudio(playing); + } - // - // Release audio with locking. Must not call into Miles! - // - releasePlayingAudioInListIfStopped(m_playingSounds, m_playingSoundsCS); - releasePlayingAudioInListIfStopped(m_playing3DSounds, m_playing3DSoundsCS); - releasePlayingAudioInListIfStopped(m_playingStreams, m_playingStreamsCS); - releasePlayingAudioInListIfStopped(m_fadingAudio, m_fadingAudioCS); + // + // Release audio with locking. Must not call into Miles! + // + releasePlayingAudioInListIfStopped(m_playingSounds, m_playingSoundsCS); + releasePlayingAudioInListIfStopped(m_playing3DSounds, m_playing3DSoundsCS); + releasePlayingAudioInListIfStopped(m_playingStreams, m_playingStreamsCS); + releasePlayingAudioInListIfStopped(m_fadingAudio, m_fadingAudioCS); - DEBUG_ASSERTCRASH(m_playingSounds.empty(), ("List is expected to be empty now")); - DEBUG_ASSERTCRASH(m_playing3DSounds.empty(), ("List is expected to be empty now")); - DEBUG_ASSERTCRASH(m_playingStreams.empty(), ("List is expected to be empty now")); - DEBUG_ASSERTCRASH(m_fadingAudio.empty(), ("List is expected to be empty now")); + DEBUG_ASSERTCRASH(m_playingSounds.empty(), ("List is expected to be empty now")); + DEBUG_ASSERTCRASH(m_playing3DSounds.empty(), ("List is expected to be empty now")); + DEBUG_ASSERTCRASH(m_playingStreams.empty(), ("List is expected to be empty now")); + DEBUG_ASSERTCRASH(m_fadingAudio.empty(), ("List is expected to be empty now")); - std::list::iterator hit; - for (hit = m_audioForcePlayed.begin(); hit != m_audioForcePlayed.end(); ++hit) { - if (*hit) { - AIL_quick_unload(*hit); - } - } + std::list::iterator hit; + for (hit = m_audioForcePlayed.begin(); hit != m_audioForcePlayed.end(); ++hit) { + if (*hit) { + AIL_quick_unload(*hit); + } + } - m_audioForcePlayed.clear(); + m_audioForcePlayed.clear(); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::freeAllMilesHandles() { - // First, we need to ensure that we don't have any sample handles open. To that end, we must stop - // all of our currently playing audio. - stopAllAudioImmediately(); + // First, we need to ensure that we don't have any sample handles open. To that end, we must stop + // all of our currently playing audio. + stopAllAudioImmediately(); - // Walks through the available 2-D and 3-D handles and releases them - std::vector::iterator it; - for (it = m_availableSamples.begin(); it != m_availableSamples.end(); ++it) { - AIL_release_sample_handle(*it); - } + // Walks through the available 2-D and 3-D handles and releases them + std::vector::iterator it; + for ( it = m_availableSamples.begin(); it != m_availableSamples.end(); ++it ) { + AIL_release_sample_handle(*it); + } - m_availableSamples.clear(); - m_num2DSamples = 0; + m_availableSamples.clear(); + m_num2DSamples = 0; - std::vector::iterator it3D; - for (it3D = m_available3DSamples.begin(); it3D != m_available3DSamples.end(); ++it3D) { - AIL_release_3D_sample_handle(*it3D); - } + std::vector::iterator it3D; + for ( it3D = m_available3DSamples.begin(); it3D != m_available3DSamples.end(); ++it3D ) { + AIL_release_3D_sample_handle(*it3D); + } - m_available3DSamples.clear(); - m_num3DSamples = 0; - m_numStreams = 0; + m_available3DSamples.clear(); + m_num3DSamples = 0; + m_numStreams = 0; } //------------------------------------------------------------------------------------------------- -HSAMPLE MilesAudioManager::getAvailable2DSample(AudioEventRTS* event) +HSAMPLE MilesAudioManager::getAvailable2DSample( AudioEventRTS *event ) { - if (!m_availableSamples.empty()) { - HSAMPLE retSample = m_availableSamples.back(); - m_availableSamples.pop_back(); - return retSample; - } + if (!m_availableSamples.empty()) { + HSAMPLE retSample = m_availableSamples.back(); + m_availableSamples.pop_back(); + return retSample; + } - // Find the first sample of lower priority than my augmented priority that is interruptible and take its handle - return nullptr; + // Find the first sample of lower priority than my augmented priority that is interruptible and take its handle + return nullptr; } //------------------------------------------------------------------------------------------------- -H3DSAMPLE MilesAudioManager::getAvailable3DSample(AudioEventRTS* event) +H3DSAMPLE MilesAudioManager::getAvailable3DSample( AudioEventRTS *event ) { - if (!m_available3DSamples.empty()) { - H3DSAMPLE retSample = m_available3DSamples.back(); - m_available3DSamples.pop_back(); - return retSample; - } + if (!m_available3DSamples.empty()) { + H3DSAMPLE retSample = m_available3DSamples.back(); + m_available3DSamples.pop_back(); + return retSample; + } - // Find the first sample of lower priority than my augmented priority that is interruptible and take its handle - return nullptr; + // Find the first sample of lower priority than my augmented priority that is interruptible and take its handle + return nullptr; } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::adjustPlayingVolume(PlayingAudio* audio) +void MilesAudioManager::adjustPlayingVolume( PlayingAudio *playing ) { - Real pan; - if (audio->m_type == PAT_Sample) { - AIL_sample_volume_pan(audio->m_sample, nullptr, &pan); - AIL_set_sample_volume_pan(audio->m_sample, getEffectiveVolume(audio->m_audioEventRTS), pan); + Real pan; + if (playing->m_type == PAT_Sample) { + AIL_sample_volume_pan(playing->m_sample, nullptr, &pan); + AIL_set_sample_volume_pan(playing->m_sample, getEffectiveVolume(playing->m_audioEventRTS.Peek()), pan); - } - else if (audio->m_type == PAT_3DSample) { - AIL_set_3D_sample_volume(audio->m_3DSample, getEffectiveVolume(audio->m_audioEventRTS)); + } else if (playing->m_type == PAT_3DSample) { + AIL_set_3D_sample_volume(playing->m_3DSample, getEffectiveVolume(playing->m_audioEventRTS.Peek())); - } - else if (audio->m_type == PAT_Stream) { - AIL_stream_volume_pan(audio->m_stream, nullptr, &pan); - if (audio->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - AIL_set_stream_volume_pan(audio->m_stream, getEffectiveVolume(audio->m_audioEventRTS), pan); + } else if (playing->m_type == PAT_Stream) { + AIL_stream_volume_pan(playing->m_stream, nullptr, &pan); + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music ) { + AIL_set_stream_volume_pan(playing->m_stream, getEffectiveVolume(playing->m_audioEventRTS.Peek()), pan); - } - else { - AIL_set_stream_volume_pan(audio->m_stream, getEffectiveVolume(audio->m_audioEventRTS), pan); + } else { + AIL_set_stream_volume_pan(playing->m_stream, getEffectiveVolume(playing->m_audioEventRTS.Peek()), pan); - } - } + } + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::stopAllSpeech() { - std::list::iterator it; - PlayingAudio* playing; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = (*it); - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) { - stopPlayingAudio(playing); - } - } + std::list::iterator it; + PlayingAudio *playing; + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = (*it); + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) { + stopPlayingAudio(playing); + } + } } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::initFilters(HSAMPLE sample, AudioEventRTS* event) +void MilesAudioManager::initFilters( HSAMPLE sample, AudioEventRTS *event ) { - // set the sample volume - AIL_set_sample_volume_pan(sample, getEffectiveVolume(event), 0.5f); + // set the sample volume + AIL_set_sample_volume_pan(sample, getEffectiveVolume(event), 0.5f); - // pitch shift - Real pitchShift = event->getPitchShift(); - if (pitchShift == 0.0f) { - DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str())); - } - else { - AIL_set_sample_playback_rate(sample, REAL_TO_INT(AIL_sample_playback_rate(sample) * pitchShift)); - } + // pitch shift + Real pitchShift = event->getPitchShift(); + if (pitchShift == 0.0f) { + DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str()) ); + } else { + AIL_set_sample_playback_rate(sample, REAL_TO_INT(AIL_sample_playback_rate(sample) * pitchShift)); + } - // set up delay filter, if applicable - if (event->getDelay() > 0.0f) { - Real value; - value = event->getDelay(); - AIL_set_sample_processor(sample, DP_FILTER, m_delayFilter); - AIL_set_filter_sample_preference(sample, "Mono Delay Time", &value); + // set up delay filter, if applicable + if (event->getDelay() > 0.0f) { + Real value; + value = event->getDelay(); + AIL_set_sample_processor(sample, DP_FILTER, m_delayFilter); + AIL_set_filter_sample_preference(sample, "Mono Delay Time", &value); - value = 0.0; - AIL_set_filter_sample_preference(sample, "Mono Delay", &value); - AIL_set_filter_sample_preference(sample, "Mono Delay Mix", &value); - } + value = 0.0; + AIL_set_filter_sample_preference(sample, "Mono Delay", &value); + AIL_set_filter_sample_preference(sample, "Mono Delay Mix", &value); + } } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::initFilters3D(H3DSAMPLE sample, AudioEventRTS* event, const Coord3D* pos) +void MilesAudioManager::initFilters3D( H3DSAMPLE sample, AudioEventRTS *event, const Coord3D *pos ) { - // set the sample volume - AIL_set_3D_sample_volume(sample, getEffectiveVolume(event)); + // set the sample volume + AIL_set_3D_sample_volume(sample, getEffectiveVolume(event)); - // pitch shift - Real pitchShift = event->getPitchShift(); - if (pitchShift == 0.0f) { - DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str())); - } - else { - AIL_set_3D_sample_playback_rate(sample, REAL_TO_INT(AIL_3D_sample_playback_rate(sample) * pitchShift)); - } + // pitch shift + Real pitchShift = event->getPitchShift(); + if (pitchShift == 0.0f) { + DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str()) ); + } else { + AIL_set_3D_sample_playback_rate(sample, REAL_TO_INT(AIL_3D_sample_playback_rate(sample) * pitchShift)); + } - // Low pass filter - if (event->getAudioEventInfo()->m_lowPassFreq > 0 && !isOnScreen(pos)) { - AIL_set_3D_sample_occlusion(sample, 1.0f - event->getAudioEventInfo()->m_lowPassFreq); - } + // Low pass filter + if (event->getAudioEventInfo()->m_lowPassFreq > 0 && !isOnScreen(pos) ) { + AIL_set_3D_sample_occlusion(sample, 1.0f - event->getAudioEventInfo()->m_lowPassFreq); + } } //------------------------------------------------------------------------------------------------- AsciiString MilesAudioManager::nextMusicTrack() { - AsciiString trackName; + AsciiString trackName; - if (PlayingAudio* playing = findActiveMusic()) { - trackName = playing->m_audioEventRTS->getEventName(); - } + if (PlayingAudio *playing = findActiveMusic()) { + trackName = playing->m_audioEventRTS->getEventName(); + } - // Stop currently playing music - TheAudio->removeAudioEvent(AHSV_StopTheMusic); + // Stop currently playing music + TheAudio->removeAudioEvent(AHSV_StopTheMusic); - trackName = nextTrackName(trackName); - AudioEventRTS newTrack(trackName); - TheAudio->addAudioEvent(&newTrack); + trackName = nextTrackName(trackName); + AudioEventRTS newTrack(trackName); + TheAudio->addAudioEvent(&newTrack); - return trackName; + return trackName; } //------------------------------------------------------------------------------------------------- AsciiString MilesAudioManager::prevMusicTrack() { - AsciiString trackName; + AsciiString trackName; - if (PlayingAudio* playing = findActiveMusic()) { - trackName = playing->m_audioEventRTS->getEventName(); - } + if (PlayingAudio *playing = findActiveMusic()) { + trackName = playing->m_audioEventRTS->getEventName(); + } - // Stop currently playing music - TheAudio->removeAudioEvent(AHSV_StopTheMusic); + // Stop currently playing music + TheAudio->removeAudioEvent(AHSV_StopTheMusic); - trackName = prevTrackName(trackName); - AudioEventRTS newTrack(trackName); - TheAudio->addAudioEvent(&newTrack); + trackName = prevTrackName(trackName); + AudioEventRTS newTrack(trackName); + TheAudio->addAudioEvent(&newTrack); - return trackName; + return trackName; } //------------------------------------------------------------------------------------------------- Bool MilesAudioManager::isMusicPlaying() const { - return findActiveMusic() != nullptr; + return findActiveMusic() != nullptr; } //------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::hasMusicTrackCompleted(const AsciiString& trackName, Int numberOfTimes) const +Bool MilesAudioManager::hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const { - if (const PlayingAudio* playing = findActiveMusic(&trackName)) { - if (INFINITE_LOOP_COUNT - AIL_stream_loop_count(playing->m_stream) >= numberOfTimes) { - return TRUE; - } - } - return FALSE; + if (const PlayingAudio *playing = findActiveMusic(&trackName)) { + if (INFINITE_LOOP_COUNT - AIL_stream_loop_count(playing->m_stream) >= numberOfTimes) { + return TRUE; + } + } + return FALSE; } //------------------------------------------------------------------------------------------------- void MilesAudioManager::openDevice() { - if (!TheGlobalData->m_audioOn) { - return; - } + if (!TheGlobalData->m_audioOn) { + return; + } - AIL_set_redist_directory("MSS\\"); - AIL_startup(); - Int retval = 0; + AIL_set_redist_directory("MSS\\"); + AIL_startup(); + Int retval = 0; - // AIL_quick_startup should be replaced later with a call to actually pick which device to use, etc - const AudioSettings* audioSettings = getAudioSettings(); - m_selectedSpeakerType = TheAudio->translateSpeakerTypeToUnsignedInt(m_prefSpeaker); + // AIL_quick_startup should be replaced later with a call to actually pick which device to use, etc + const AudioSettings *audioSettings = getAudioSettings(); + m_selectedSpeakerType = TheAudio->translateSpeakerTypeToUnsignedInt(m_prefSpeaker); - retval = AIL_quick_startup(audioSettings->m_useDigital, audioSettings->m_useMidi, audioSettings->m_outputRate, audioSettings->m_outputBits, audioSettings->m_outputChannels); + retval = AIL_quick_startup(audioSettings->m_useDigital, audioSettings->m_useMidi, audioSettings->m_outputRate, audioSettings->m_outputBits, audioSettings->m_outputChannels); - // Quick handles tells us where to store the various devices. For now, we're only interested in the digital handle. - AIL_quick_handles(&m_digitalHandle, nullptr, nullptr); + // Quick handles tells us where to store the various devices. For now, we're only interested in the digital handle. + AIL_quick_handles(&m_digitalHandle, nullptr, nullptr); - if (retval) { - buildProviderList(); - } - else { - // if we couldn't initialize any devices, turn sound off (fail silently) - setOn(false, AudioAffect_All); - } + if (retval) { + buildProviderList(); + } else { + // if we couldn't initialize any devices, turn sound off (fail silently) + setOn( false, AudioAffect_All ); + } - selectProvider(TheAudio->getProviderIndex(m_pref3DProvider)); + selectProvider(TheAudio->getProviderIndex(m_pref3DProvider)); - // Now that we're all done, update the cached variables so that everything is in sync. - TheAudio->refreshCachedVariables(); + // Now that we're all done, update the cached variables so that everything is in sync. + TheAudio->refreshCachedVariables(); - if (!isValidProvider()) { - return; - } + if (!isValidProvider()) { + return; + } - initDelayFilter(); + initDelayFilter(); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::closeDevice() { - freeAllMilesHandles(); - unselectProvider(); - AIL_shutdown(); -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::isCurrentlyPlaying(AudioHandle handle) -{ - std::list::iterator it; - PlayingAudio* playing; - - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getPlayingHandle() == handle) { - return true; - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getPlayingHandle() == handle) { - return true; - } - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getPlayingHandle() == handle) { - return true; - } - } - - // if something is requested, it is also considered playing - std::list::iterator ait; - AudioRequest* req = nullptr; - for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ++ait) { - req = *ait; - if (req->m_usePendingEvent && req->m_pendingEvent->getPlayingHandle() == handle) { - return true; - } - } - - return false; -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::notifyOfAudioCompletion(UnsignedInt handle, UnsignedInt flags) -{ - PlayingAudio* playing = findPlayingAudioFrom(handle, flags); - if (!playing) { - DEBUG_CRASH(("Audio has completed playing, but we can't seem to find it. - jkmcd")); - return; - } - - if (getDisallowSpeech() && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) { - setDisallowSpeech(FALSE); - } - - if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_LOOP) { - if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Attack) { - playing->m_audioEventRTS->setNextPlayPortion(PP_Sound); - } - if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Sound) { - // First, decrease the loop count. - playing->m_audioEventRTS->decreaseLoopCount(); - - // Now, try to start the next loop - if (startNextLoop(playing)) { - return; - } - } - } - - playing->m_audioEventRTS->advanceNextPlayPortion(); - if (playing->m_audioEventRTS->getNextPlayPortion() != PP_Done) { - if (playing->m_type == PAT_Sample) { - closeFile(playing->m_file); // close it so as not to leak it. - playing->m_file = playSample(playing->m_audioEventRTS, playing->m_sample); - - // If we don't have a file now, then we should drop to the stopped status so that - // We correctly close this handle. - if (playing->m_file) { - return; - } - } - else if (playing->m_type == PAT_3DSample) { - closeFile(playing->m_file); // close it so as not to leak it. - playing->m_file = playSample3D(playing->m_audioEventRTS, playing->m_3DSample); - - // If we don't have a file now, then we should drop to the stopped status so that - // We correctly close this handle. - if (playing->m_file) { - return; - } - } - } - - if (playing->m_type == PAT_Stream) { - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - playStream(playing->m_audioEventRTS, playing->m_stream); - return; - } - } - - // it will be cleaned up on the next frame update - InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); -} - -//------------------------------------------------------------------------------------------------- -PlayingAudio* MilesAudioManager::findPlayingAudioFrom(UnsignedInt handle, UnsignedInt flags) -{ - std::list::iterator it; - PlayingAudio* playing; - - if (flags == PAT_Sample) { - HSAMPLE sample = (HSAMPLE)handle; - CriticalSectionClass::LockClass lock(m_playingSoundsCS); - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - if (playing->m_sample == sample) { - return playing; - } - } - } - - if (flags == PAT_3DSample) { - H3DSAMPLE sample3D = (H3DSAMPLE)handle; - CriticalSectionClass::LockClass lock(m_playing3DSoundsCS); - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - if (playing->m_3DSample == sample3D) { - return playing; - } - } - } - - if (flags == PAT_Stream) { - HSTREAM stream = (HSTREAM)handle; - { - CriticalSectionClass::LockClass lock(m_playingStreamsCS); - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_stream == stream) { - return playing; - } - } - } - { - CriticalSectionClass::LockClass lock(m_fadingAudioCS); - for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { - playing = *it; - if (playing->m_stream == stream) { - return playing; - } - } - } - } - - return nullptr; + freeAllMilesHandles(); + unselectProvider(); + AIL_shutdown(); +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::isCurrentlyPlaying( AudioHandle handle ) +{ + std::list::iterator it; + PlayingAudio *playing; + + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + if (!playing->isPlayingOrRequested()) { + continue; + } + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + return true; + } + } + + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + if (!playing->isPlayingOrRequested()) { + continue; + } + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + return true; + } + } + + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (!playing->isPlayingOrRequested()) { + continue; + } + if (playing->m_audioEventRTS->getPlayingHandle() == handle) { + return true; + } + } + + // if something is requested, it is also considered playing + std::list::iterator ait; + AudioRequest *req = nullptr; + for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ++ait) { + req = *ait; + if (req->m_pendingEvent && req->m_pendingEvent->getPlayingHandle() == handle) { + return true; + } + } + + return false; +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt handle, UnsignedInt flags ) +{ + PlayingAudio *playing = findPlayingAudioFrom(handle, flags); + if (!playing) { + DEBUG_CRASH(("Audio has completed playing, but we can't seem to find it. - jkmcd")); + return; + } + + if (getDisallowSpeech() && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) { + setDisallowSpeech(FALSE); + } + + if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_LOOP) { + if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Attack) { + playing->m_audioEventRTS->setNextPlayPortion(PP_Sound); + } + if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Sound) { + // First, decrease the loop count. + playing->m_audioEventRTS->decreaseLoopCount(); + + // Now, try to start the next loop + if (startNextLoop(playing)) { + return; + } + } + } + + playing->m_audioEventRTS->advanceNextPlayPortion(); + + switch (playing->m_type) + { + case PAT_Sample: + { + if (playing->m_audioEventRTS->getNextPlayPortion() != PP_Done) { + closeFile(playing->m_file); // close it so as not to leak it. + playing->m_file = playSample(playing->m_audioEventRTS.Peek(), playing->m_sample); + + // If we don't have a file now, then we should drop to the stopped status so that + // We correctly close this handle. + if (playing->m_file) { + return; + } + } + break; + } + case PAT_3DSample: + { + if (playing->m_audioEventRTS->getNextPlayPortion() != PP_Done) { + closeFile(playing->m_file); // close it so as not to leak it. + playing->m_file = playSample3D(playing->m_audioEventRTS.Peek(), playing->m_3DSample); + + // If we don't have a file now, then we should drop to the stopped status so that + // We correctly close this handle. + if (playing->m_file) { + return; + } + } + break; + } + case PAT_Stream: + { + if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + playStream(playing->m_audioEventRTS.Peek(), playing->m_stream); + return; + } + break; + } + } + + // it will be cleaned up on the next frame update + InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); +} + +//------------------------------------------------------------------------------------------------- +PlayingAudio *MilesAudioManager::findPlayingAudioFrom( UnsignedInt handle, UnsignedInt flags ) +{ + std::list::iterator it; + PlayingAudio *playing; + + if (flags == PAT_Sample) { + HSAMPLE sample = (HSAMPLE) handle; + CriticalSectionClass::LockClass lock(m_playingSoundsCS); + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + if (playing->m_sample == sample) { + return playing; + } + } + } + + if (flags == PAT_3DSample) { + H3DSAMPLE sample3D = (H3DSAMPLE) handle; + CriticalSectionClass::LockClass lock(m_playing3DSoundsCS); + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + if (playing->m_3DSample == sample3D) { + return playing; + } + } + } + + if (flags == PAT_Stream) { + HSTREAM stream = (HSTREAM) handle; + { + CriticalSectionClass::LockClass lock(m_playingStreamsCS); + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (playing->m_stream == stream) { + return playing; + } + } + } + { + CriticalSectionClass::LockClass lock(m_fadingAudioCS); + for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { + playing = *it; + if (playing->m_stream == stream) { + return playing; + } + } + } + } + + return nullptr; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getProviderCount() const { - return m_providerCount; -} - -//------------------------------------------------------------------------------------------------- -AsciiString MilesAudioManager::getProviderName(UnsignedInt providerNum) const -{ - if (isOn(AudioAffect_Sound3D) && providerNum < m_providerCount) { - return m_provider3D[providerNum].name; - } - - return AsciiString::TheEmptyString; -} - -//------------------------------------------------------------------------------------------------- -UnsignedInt MilesAudioManager::getProviderIndex(AsciiString providerName) const -{ - for (UnsignedInt i = 0; i < m_providerCount; ++i) { - if (providerName == m_provider3D[i].name) { - return i; - } - } - - return PROVIDER_ERROR; -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::selectProvider(UnsignedInt providerNdx) -{ - if (!isOn(AudioAffect_Sound3D)) - { - return; - } - - if (providerNdx == m_selectedProvider) - { - return; - } - - if (isValidProvider()) - { - freeAllMilesHandles(); - unselectProvider(); - } - - LPDIRECTSOUND lpDirectSoundInfo; - AIL_get_DirectSound_info(nullptr, (void**)&lpDirectSoundInfo, nullptr); - Bool useDolby = FALSE; - if (lpDirectSoundInfo) - { - DWORD speakerConfig; - lpDirectSoundInfo->GetSpeakerConfig(&speakerConfig); - switch (DSSPEAKER_CONFIG(speakerConfig)) - { - case DSSPEAKER_DIRECTOUT: - m_selectedSpeakerType = AIL_3D_2_SPEAKER; - break; - case DSSPEAKER_MONO: - m_selectedSpeakerType = AIL_3D_2_SPEAKER; - break; - case DSSPEAKER_STEREO: - m_selectedSpeakerType = AIL_3D_2_SPEAKER; - break; - case DSSPEAKER_HEADPHONE: - m_selectedSpeakerType = AIL_3D_HEADPHONE; - useDolby = TRUE; - break; - case DSSPEAKER_QUAD: - m_selectedSpeakerType = AIL_3D_4_SPEAKER; - useDolby = TRUE; - break; - case DSSPEAKER_SURROUND: - m_selectedSpeakerType = AIL_3D_SURROUND; - useDolby = TRUE; - break; - case DSSPEAKER_5POINT1: - m_selectedSpeakerType = AIL_3D_51_SPEAKER; - useDolby = TRUE; - break; - case DSSPEAKER_7POINT1: - m_selectedSpeakerType = AIL_3D_71_SPEAKER; - useDolby = TRUE; - break; - } - } - - Bool success = FALSE; - if (useDolby) - { - providerNdx = getProviderIndex("Dolby Surround"); - } - else - { - providerNdx = getProviderIndex("Miles Fast 2D Positional Audio"); - } - success = AIL_open_3D_provider(m_provider3D[providerNdx].id) == 0; - - //if (providerNdx < m_providerCount) - //{ - // failed = AIL_open_3D_provider(m_provider3D[providerNdx].id); - //} - - - - if (!success) - { - m_selectedProvider = PROVIDER_ERROR; - // try to select a failsafe - providerNdx = getProviderIndex("Miles Fast 2D Positional Audio"); - success = AIL_open_3D_provider(m_provider3D[providerNdx].id) == 0; - } - - if (success) - { - m_selectedProvider = providerNdx; - - initSamplePools(); - - createListener(); - setSpeakerType(m_selectedSpeakerType); - if (TheVideoPlayer) - { - TheVideoPlayer->notifyVideoPlayerOfNewProvider(TRUE); - } - } + return m_providerCount; +} + +//------------------------------------------------------------------------------------------------- +AsciiString MilesAudioManager::getProviderName( UnsignedInt providerNum ) const +{ + if (isOn(AudioAffect_Sound3D) && providerNum < m_providerCount) { + return m_provider3D[providerNum].name; + } + + return AsciiString::TheEmptyString; +} + +//------------------------------------------------------------------------------------------------- +UnsignedInt MilesAudioManager::getProviderIndex( AsciiString providerName ) const +{ + for (UnsignedInt i = 0; i < m_providerCount; ++i) { + if (providerName == m_provider3D[i].name) { + return i; + } + } + + return PROVIDER_ERROR; +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::selectProvider( UnsignedInt providerNdx ) +{ + if (!isOn(AudioAffect_Sound3D)) + { + return; + } + + if (providerNdx == m_selectedProvider) + { + return; + } + + if (isValidProvider()) + { + freeAllMilesHandles(); + unselectProvider(); + } + + LPDIRECTSOUND lpDirectSoundInfo; + AIL_get_DirectSound_info( nullptr, (void**)&lpDirectSoundInfo, nullptr ); + Bool useDolby = FALSE; + if( lpDirectSoundInfo ) + { + DWORD speakerConfig; + lpDirectSoundInfo->GetSpeakerConfig( &speakerConfig ); + switch( DSSPEAKER_CONFIG( speakerConfig ) ) + { + case DSSPEAKER_DIRECTOUT: + m_selectedSpeakerType = AIL_3D_2_SPEAKER; + break; + case DSSPEAKER_MONO: + m_selectedSpeakerType = AIL_3D_2_SPEAKER; + break; + case DSSPEAKER_STEREO: + m_selectedSpeakerType = AIL_3D_2_SPEAKER; + break; + case DSSPEAKER_HEADPHONE: + m_selectedSpeakerType = AIL_3D_HEADPHONE; + useDolby = TRUE; + break; + case DSSPEAKER_QUAD: + m_selectedSpeakerType = AIL_3D_4_SPEAKER; + useDolby = TRUE; + break; + case DSSPEAKER_SURROUND: + m_selectedSpeakerType = AIL_3D_SURROUND; + useDolby = TRUE; + break; + case DSSPEAKER_5POINT1: + m_selectedSpeakerType = AIL_3D_51_SPEAKER; + useDolby = TRUE; + break; + case DSSPEAKER_7POINT1: + m_selectedSpeakerType = AIL_3D_71_SPEAKER; + useDolby = TRUE; + break; + } + } + + Bool success = FALSE; + if( useDolby ) + { + providerNdx = getProviderIndex( "Dolby Surround" ); + } + else + { + providerNdx = getProviderIndex( "Miles Fast 2D Positional Audio" ); + } + success = AIL_open_3D_provider( m_provider3D[providerNdx].id ) == 0; + + //if (providerNdx < m_providerCount) + //{ + // failed = AIL_open_3D_provider(m_provider3D[providerNdx].id); + //} + + + + if( !success ) + { + m_selectedProvider = PROVIDER_ERROR; + // try to select a failsafe + providerNdx = getProviderIndex( "Miles Fast 2D Positional Audio" ); + success = AIL_open_3D_provider( m_provider3D[providerNdx].id ) == 0; + } + + if ( success ) + { + m_selectedProvider = providerNdx; + + initSamplePools(); + + createListener(); + setSpeakerType(m_selectedSpeakerType); + if (TheVideoPlayer) + { + TheVideoPlayer->notifyVideoPlayerOfNewProvider(TRUE); + } + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::unselectProvider() { - if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { - return; - } + if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { + return; + } - if (TheVideoPlayer) { - TheVideoPlayer->notifyVideoPlayerOfNewProvider(FALSE); - } - AIL_close_3D_listener(m_listener); - m_listener = nullptr; + if (TheVideoPlayer) { + TheVideoPlayer->notifyVideoPlayerOfNewProvider(FALSE); + } + AIL_close_3D_listener(m_listener); + m_listener = nullptr; - AIL_close_3D_provider(m_provider3D[m_selectedProvider].id); - m_lastProvider = m_selectedProvider; + AIL_close_3D_provider(m_provider3D[m_selectedProvider].id); + m_lastProvider = m_selectedProvider; - m_selectedProvider = PROVIDER_ERROR; + m_selectedProvider = PROVIDER_ERROR; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getSelectedProvider() const { - return m_selectedProvider; + return m_selectedProvider; } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::setSpeakerType(UnsignedInt speakerType) +void MilesAudioManager::setSpeakerType( UnsignedInt speakerType ) { - if (!isValidProvider()) { - return; - } + if (!isValidProvider()) { + return; + } - AIL_set_3D_speaker_type(m_provider3D[m_selectedProvider].id, speakerType); - m_selectedSpeakerType = speakerType; + AIL_set_3D_speaker_type( m_provider3D[m_selectedProvider].id, speakerType ); + m_selectedSpeakerType = speakerType; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getSpeakerType() { - if (!isValidProvider()) { - return 0; - } + if (!isValidProvider()) { + return 0; + } - return m_selectedSpeakerType; + return m_selectedSpeakerType; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getNum2DSamples() const { - return m_num2DSamples; + return m_num2DSamples; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getNum3DSamples() const { - return m_num3DSamples; + return m_num3DSamples; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getNumStreams() const { - return m_numStreams; + return m_numStreams; } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getNumAvailable2DSamples() const { - return (UnsignedInt)m_availableSamples.size(); + return (UnsignedInt)m_availableSamples.size(); } //------------------------------------------------------------------------------------------------- UnsignedInt MilesAudioManager::getNumAvailable3DSamples() const { - return (UnsignedInt)m_available3DSamples.size(); -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::doesViolateLimit(AudioEventRTS* event) const -{ - Int limit = event->getAudioEventInfo()->m_limit; - if (limit == 0) { - return false; - } - - Int totalCount = 0; - Int totalRequestCount = 0; - - std::list::const_iterator it; - if (!event->isPositionalAudio()) { - // 2-D - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { - if (totalCount == 0) { - // This is the oldest audio of this type playing. - event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); - } - ++totalCount; - } - } - } - else { - // 3-D - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { - if (totalCount == 0) { - // This is the oldest audio of this type playing. - event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); - } - ++totalCount; - } - } - } - - // Also check the request list in case we've requested to play this sound. - std::list::const_iterator arIt; - for (arIt = m_audioRequests.begin(); arIt != m_audioRequests.end(); ++arIt) { - AudioRequest* req = (*arIt); - if (req->m_usePendingEvent) - { - if (req->m_pendingEvent->getEventName() == event->getEventName()) - { - totalRequestCount++; - totalCount++; - } - } - } - - //If our event is an interrupting type, then normally we would always add it. The exception is when we have requested - //multiple sounds in the same frame and those requests violate the limit. Because we don't have any "old" sounds to - //remove in the case of an interrupt, we need to catch it early and prevent the sound from being added if we already - //reached the limit - if (event->getAudioEventInfo()->m_control & AC_INTERRUPT) - { - if (totalRequestCount < limit) - { - Int totalPlayingCount = totalCount - totalRequestCount; - if (totalRequestCount + totalPlayingCount < limit) - { - //We aren't exceeding the actual limit, then clear the kill handle. - event->setHandleToKill(0); - return false; - } - - //We are exceeding the limit - the kill handle will kill the - //oldest playing sound to enforce the actual limit. - return false; - } - } - - if (totalCount < limit) - { - event->setHandleToKill(0); - return false; - } - - return true; -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::isPlayingAlready(AudioEventRTS* event) const -{ - std::list::const_iterator it; - if (!event->isPositionalAudio()) { - // 2-D - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { - return true; - } - } - } - else { - // 3-D - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { - return true; - } - } - } - - return false; -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::isObjectPlayingVoice(UnsignedInt objID) const -{ - if (objID == 0) { - return false; - } - - std::list::const_iterator it; - // 2-D - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) { - return true; - } - } - - // 3-D - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) { - return true; - } - } - - return false; -} - -//------------------------------------------------------------------------------------------------- -AudioEventRTS* MilesAudioManager::findLowestPrioritySound(AudioEventRTS* event) -{ - AudioPriority priority = event->getAudioEventInfo()->m_priority; - if (priority == AP_LOWEST) - { - //If the event we pass in is the lowest priority, don't bother checking because - //there is nothing lower priority than lowest. - return nullptr; - } - AudioEventRTS* lowestPriorityEvent = nullptr; - AudioPriority lowestPriority; - - std::list::const_iterator it; - if (event->isPositionalAudio()) - { - //3D - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) - { - AudioEventRTS* itEvent = (*it)->m_audioEventRTS; - AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority; - if (itPriority < priority) - { - if (!lowestPriorityEvent || lowestPriority > itPriority) - { - lowestPriorityEvent = itEvent; - lowestPriority = itPriority; - if (lowestPriority == AP_LOWEST) - { - return lowestPriorityEvent; - } - } - } - } - } - else - { - //2D - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) - { - AudioEventRTS* itEvent = (*it)->m_audioEventRTS; - AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority; - if (itPriority < priority) - { - if (!lowestPriorityEvent || lowestPriority > itPriority) - { - lowestPriorityEvent = itEvent; - lowestPriority = itPriority; - if (lowestPriority == AP_LOWEST) - { - return lowestPriorityEvent; - } - } - } - } - } - return lowestPriorityEvent; -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::isPlayingLowerPriority(AudioEventRTS* event) const -{ - //We don't actually want to do anything to this CONST function. Remember, we're - //just checking to see if there is a lower priority sound. - AudioPriority priority = event->getAudioEventInfo()->m_priority; - if (priority == AP_LOWEST) - { - //If the event we pass in is the lowest priority, don't bother checking because - //there is nothing lower priority than lowest. - return false; - } - std::list::const_iterator it; - if (!event->isPositionalAudio()) { - // 2-D - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) { - //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); - return true; - } - } - } - else { - // 3-D - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) { - //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); - return true; - } - } - } - - return false; -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::killLowestPrioritySoundImmediately(AudioEventRTS* event) -{ - //Actually, we want to kill the LOWEST PRIORITY SOUND, not the first "lower" priority - //sound we find, because it could easily be - AudioEventRTS* lowestPriorityEvent = findLowestPrioritySound(event); - if (lowestPriorityEvent) - { - std::list::iterator it; - if (event->isPositionalAudio()) - { - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) - { - PlayingAudio* playing = (*it); - - if (playing->m_audioEventRTS && playing->m_audioEventRTS == lowestPriorityEvent) - { - //Release this 3D sound channel immediately because we are going to play another sound in it's place. - stopPlayingAudio(playing); - return TRUE; - } - } - } - else - { - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) - { - PlayingAudio* playing = (*it); - - if (playing->m_audioEventRTS && playing->m_audioEventRTS == lowestPriorityEvent) - { - //Release this sound channel immediately because we are going to play another sound in it's place. - stopPlayingAudio(playing); - return TRUE; - } - } - } - } - return FALSE; + return (UnsignedInt)m_available3DSamples.size(); +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::doesViolateLimit( AudioEventRTS *event ) const +{ + Int limit = event->getAudioEventInfo()->m_limit; + if (limit == 0) { + return false; + } + + Int totalCount = 0; + Int totalRequestCount = 0; + + std::list::const_iterator it; + if (!event->isPositionalAudio()) { + // 2-D + for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + if (!(*it)->isPlayingOrRequested()) { + continue; + } + if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { + if (totalCount == 0) { + // This is the oldest audio of this type playing. + event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); + } + ++totalCount; + } + } + } else { + // 3-D + for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + if (!(*it)->isPlayingOrRequested()) { + continue; + } + if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { + if (totalCount == 0) { + // This is the oldest audio of this type playing. + event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); + } + ++totalCount; + } + } + } + + // Also check the request list in case we've requested to play this sound. + std::list::const_iterator arIt; + for (arIt = m_audioRequests.begin(); arIt != m_audioRequests.end(); ++arIt) { + AudioRequest *req = (*arIt); + if( req->m_pendingEvent && req->m_pendingEvent->getEventName() == event->getEventName() ) + { + totalRequestCount++; + totalCount++; + } + } + + //If our event is an interrupting type, then normally we would always add it. The exception is when we have requested + //multiple sounds in the same frame and those requests violate the limit. Because we don't have any "old" sounds to + //remove in the case of an interrupt, we need to catch it early and prevent the sound from being added if we already + //reached the limit + if( event->getAudioEventInfo()->m_control & AC_INTERRUPT ) + { + if( totalRequestCount < limit ) + { + Int totalPlayingCount = totalCount - totalRequestCount; + if( totalRequestCount + totalPlayingCount < limit ) + { + //We aren't exceeding the actual limit, then clear the kill handle. + event->setHandleToKill(0); + return false; + } + + //We are exceeding the limit - the kill handle will kill the + //oldest playing sound to enforce the actual limit. + return false; + } + } + + if( totalCount < limit ) + { + event->setHandleToKill(0); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::isPlayingAlready( AudioEventRTS *event ) const +{ + std::list::const_iterator it; + if (!event->isPositionalAudio()) { + // 2-D + for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { + return true; + } + } + } else { + // 3-D + for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) { + return true; + } + } + } + + return false; +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::isObjectPlayingVoice( UnsignedInt objID ) const +{ + if (objID == 0) { + return false; + } + + std::list::const_iterator it; + // 2-D + for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) { + return true; + } + } + + // 3-D + for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) { + return true; + } + } + + return false; +} + +//------------------------------------------------------------------------------------------------- +AudioEventRTS* MilesAudioManager::findLowestPrioritySound( AudioEventRTS *event ) +{ + const AudioPriority priority = event->getAudioEventInfo()->m_priority; + if( priority == AP_LOWEST ) + { + //If the event we pass in is the lowest priority, don't bother checking because + //there is nothing lower priority than lowest. + return nullptr; + } + + AudioEventRTS *lowestPriorityEvent = nullptr; + AudioPriority lowestPriority = priority; + + std::list::const_iterator it; + if( event->isPositionalAudio() ) + { + //3D + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) + { + if (!(*it)->isPlaying()) { + continue; + } + AudioEventRTS *itEvent = (*it)->m_audioEventRTS.Peek(); + const AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority; + if( itPriority < lowestPriority ) + { + lowestPriorityEvent = itEvent; + lowestPriority = itPriority; + if( lowestPriority == AP_LOWEST ) + { + return lowestPriorityEvent; + } + } + } + } + else + { + //2D + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) + { + if (!(*it)->isPlaying()) { + continue; + } + AudioEventRTS *itEvent = (*it)->m_audioEventRTS.Peek(); + const AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority; + if( itPriority < lowestPriority ) + { + lowestPriorityEvent = itEvent; + lowestPriority = itPriority; + if( lowestPriority == AP_LOWEST ) + { + return lowestPriorityEvent; + } + } + } + } + return lowestPriorityEvent; +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::isPlayingLowerPriority( AudioEventRTS *event ) const +{ + //We don't actually want to do anything to this CONST function. Remember, we're + //just checking to see if there is a lower priority sound. + AudioPriority priority = event->getAudioEventInfo()->m_priority; + if( priority == AP_LOWEST ) + { + //If the event we pass in is the lowest priority, don't bother checking because + //there is nothing lower priority than lowest. + return false; + } + std::list::const_iterator it; + if (!event->isPositionalAudio()) { + // 2-D + for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) { + //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); + return true; + } + } + } else { + // 3-D + for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + if (!(*it)->isPlaying()) { + continue; + } + if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) { + //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); + return true; + } + } + } + + return false; +} + +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::killLowestPrioritySoundImmediately( AudioEventRTS *event ) +{ + //Actually, we want to kill the LOWEST PRIORITY SOUND, not the first "lower" priority + //sound we find, because it could easily be + AudioEventRTS *lowestPriorityEvent = findLowestPrioritySound( event ); + if( lowestPriorityEvent ) + { + std::list::iterator it; + if( event->isPositionalAudio() ) + { + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) + { + PlayingAudio *playing = (*it); + if (!playing->isPlaying()) + { + continue; + } + if( playing->m_audioEventRTS.Peek() == lowestPriorityEvent ) + { + // Stop this 3D sound channel immediately because we are going to play another sound in it's place. + stopPlayingAudio(playing); + return TRUE; + } + } + } + else + { + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) + { + PlayingAudio *playing = (*it); + if (!playing->isPlaying()) + { + continue; + } + if( playing->m_audioEventRTS.Peek() == lowestPriorityEvent ) + { + // Stop this sound channel immediately because we are going to play another sound in it's place. + stopPlayingAudio(playing); + return TRUE; + } + } + } + } + return FALSE; } //------------------------------------------------------------------------------------------------- void MilesAudioManager::adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) { - Real pan; - std::list::iterator it; - - PlayingAudio* playing = nullptr; - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) { - DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); - playing->m_audioEventRTS->setVolume(newVolume); - AIL_sample_volume_pan(playing->m_sample, nullptr, &pan); - AIL_set_sample_volume_pan(playing->m_sample, getEffectiveVolume(playing->m_audioEventRTS), pan); - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) { - DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); - playing->m_audioEventRTS->setVolume(newVolume); - AIL_set_3D_sample_volume(playing->m_3DSample, getEffectiveVolume(playing->m_audioEventRTS)); - } - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) { - DEBUG_ASSERTCRASH(playing->m_stream, ("Stream is not expected to be null")); - playing->m_audioEventRTS->setVolume(newVolume); - AIL_stream_volume_pan(playing->m_stream, nullptr, &pan); - AIL_set_stream_volume_pan(playing->m_stream, getEffectiveVolume(playing->m_audioEventRTS), pan); - } - } -} - - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::removePlayingAudio(AsciiString eventName) -{ - std::list::iterator it; - - PlayingAudio* playing = nullptr; - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) - { - stopPlayingAudio(playing); - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) - { - stopPlayingAudio(playing); - } - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getEventName() == eventName) - { - stopPlayingAudio(playing); - } - } + Real pan; + std::list::iterator it; + + PlayingAudio *playing = nullptr; + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + AudioEventRTS *itEvent = playing->m_audioEventRTS.Peek(); + + if (itEvent->getEventName() == eventName) { + DEBUG_ASSERTCRASH(playing->m_sample, ("Sample is not expected to be null")); + itEvent->setVolume(newVolume); + AIL_sample_volume_pan(playing->m_sample, nullptr, &pan); + AIL_set_sample_volume_pan(playing->m_sample, getEffectiveVolume(itEvent), pan); + } + } + + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + AudioEventRTS *itEvent = playing->m_audioEventRTS.Peek(); + + if (itEvent->getEventName() == eventName) { + DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); + itEvent->setVolume(newVolume); + AIL_set_3D_sample_volume(playing->m_3DSample, getEffectiveVolume(itEvent)); + } + } + + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (!playing->isPlaying()) { + continue; + } + AudioEventRTS *itEvent = playing->m_audioEventRTS.Peek(); + + if (itEvent->getEventName() == eventName) { + DEBUG_ASSERTCRASH(playing->m_stream, ("Stream is not expected to be null")); + itEvent->setVolume(newVolume); + AIL_stream_volume_pan(playing->m_stream, nullptr, &pan); + AIL_set_stream_volume_pan(playing->m_stream, getEffectiveVolume(itEvent), pan); + } + } +} + + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::removePlayingAudio( AsciiString eventName ) +{ + std::list::iterator it; + + PlayingAudio *playing = nullptr; + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getEventName() == eventName ) + { + stopPlayingAudio(playing); + } + } + + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getEventName() == eventName ) + { + stopPlayingAudio(playing); + } + } + + for( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getEventName() == eventName ) + { + stopPlayingAudio(playing); + } + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::removeAllDisabledAudio() { - std::list::iterator it; - - PlayingAudio* playing = nullptr; - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getVolume() == 0.0f) - { - stopPlayingAudio(playing); - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getVolume() == 0.0f) - { - stopPlayingAudio(playing); - } - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) - { - playing = *it; - if (playing->m_audioEventRTS->getVolume() == 0.0f) - { - stopPlayingAudio(playing); - } - } + std::list::iterator it; + + PlayingAudio *playing = nullptr; + for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getVolume() == 0.0f ) + { + stopPlayingAudio(playing); + } + } + + for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getVolume() == 0.0f ) + { + stopPlayingAudio(playing); + } + } + + for( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) + { + playing = *it; + if( playing->m_audioEventRTS->getVolume() == 0.0f ) + { + stopPlayingAudio(playing); + } + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::processRequestList() { - std::list::iterator it; - for (it = m_audioRequests.begin(); it != m_audioRequests.end(); ) { - AudioRequest* req = (*it); - if (!shouldProcessRequestThisFrame(req)) { - adjustRequest(req); - ++it; - continue; - } + std::list::iterator it; + for (it = m_audioRequests.begin(); it != m_audioRequests.end(); ) { + AudioRequest *req = (*it); + if (!shouldProcessRequestThisFrame(req)) { + adjustRequest(req); + ++it; + continue; + } - if (!req->m_requiresCheckForSample || checkForSample(req)) { - processRequest(req); - } - deleteInstance(req); - it = m_audioRequests.erase(it); - } + if (!req->m_requiresCheckForSample || checkForSample(req)) { + processRequest(req); + } + deleteInstance(req); + it = m_audioRequests.erase(it); + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::processPlayingList() { - std::list::iterator it; - PlayingAudio* playing; - - // - // Stop audio without locking. Calls into Miles. - // Update the position of the audio if it is positional. - // - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = (*it); - - if (playing->m_status == PS_Stopping) { - stopPlayingAudio(playing); - continue; - } - - if (playing->m_status == PS_Stopped) { - continue; - } - - if (m_volumeHasChanged) - { - adjustPlayingVolume(playing); - } - } - - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = (*it); - - if (playing->m_status == PS_Stopping) { - stopPlayingAudio(playing); - continue; - } - - if (playing->m_status == PS_Stopped) { - continue; - } - - if (m_volumeHasChanged) - { - adjustPlayingVolume(playing); - } - - const Coord3D* pos = getCurrentPositionFromEvent(playing->m_audioEventRTS); - if (pos) - { - if (playing->m_audioEventRTS->isDead()) - { - stopAudioEvent(playing->m_audioEventRTS->getPlayingHandle()); - } - else - { - Real volForConsideration = getEffectiveVolume(playing->m_audioEventRTS); - volForConsideration /= (m_sound3DVolume > 0.0f ? m_soundVolume : 1.0f); - Bool playAnyways = BitIsSet(playing->m_audioEventRTS->getAudioEventInfo()->m_type, ST_GLOBAL) - || playing->m_audioEventRTS->getAudioEventInfo()->m_priority == AP_CRITICAL; - if (volForConsideration < m_audioSettings->m_minVolume && !playAnyways) - { - stopPlayingAudio(playing); - } - else - { - Real x = pos->x; - Real y = pos->y; - Real z = pos->z; - DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); - AIL_set_3D_position(playing->m_3DSample, x, y, z); - } - } - } - else - { - stopPlayingAudio(playing); - } - } - - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = (*it); - - if (playing->m_status == PS_Stopping) { - stopPlayingAudio(playing); - continue; - } - - if (playing->m_status == PS_Stopped) { - continue; - } - - if (m_volumeHasChanged) - { - adjustPlayingVolume(playing); - } - } - - // - // Release audio with locking. Must not call into Miles! - // - releasePlayingAudioInListIfStopped(m_playingSounds, m_playingSoundsCS); - releasePlayingAudioInListIfStopped(m_playing3DSounds, m_playing3DSoundsCS); - releasePlayingAudioInListIfStopped(m_playingStreams, m_playingStreamsCS); - - // - // Transfer streams to fade list when signaled. - // - { - CriticalSectionClass::LockClass lock(m_playingStreamsCS); - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ) { - playing = (*it); - - if (playing->m_fade) - { - { - CriticalSectionClass::LockClass lock(m_fadingAudioCS); - m_fadingAudio.push_back(playing); - } - it = m_playingStreams.erase(it); - continue; - } - - ++it; - } - } - - if (m_volumeHasChanged) { - m_volumeHasChanged = false; - } -} - -//Patch for a rare bug (only on about 5% of in-studio machines suffer, and not all the time) . -//The actual mechanics of this problem are still elusive as of the date of this comment. 8/21/03 -//but the cause is clear. Some cinematics do a radical change in the microphone position, which -//calls for a radical 3DSoundVolume adjustment. If this happens while a stereo stream is *ENDING*, -//low-level code gets caught in a tight loop. (Hangs) on some machines. -//To prevent this condition, we just suppress the updating of 3DSoundVolume while one of these -//is on the list. Since the music tracks play continuously, they never *END* during these cinematics. -//so we filter them out as, *NOT SENSITIVE*... we do want to update 3DSoundVolume during music, -//which is almost all of the time. - -Bool MilesAudioManager::has3DSensitiveStreamsPlaying() const -{ - if (m_playingStreams.empty()) - return FALSE; - - for (std::list< PlayingAudio* >::const_iterator it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) - { - const PlayingAudio* playing = (*it); - - if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType != AT_Music) - { - return TRUE; - } - - if (playing->m_audioEventRTS->getEventName().startsWith("Game_") == FALSE) - { - return TRUE; - } - } - - return FALSE; - + std::list::iterator it; + PlayingAudio *playing; + + // + // Stop audio without locking. Calls into Miles. + // Update the position of the audio if it is positional. + // + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { + playing = (*it); + + if (playing->m_status == PS_Stopping) { + rerequestPlayingAudioWhenSignalled(playing); + stopPlayingAudio(playing); + continue; + } + + if (playing->m_status == PS_Stopped) { + continue; + } + + if (m_volumeHasChanged) + { + adjustPlayingVolume(playing); + } + } + + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { + playing = (*it); + + if (playing->m_status == PS_Stopping) { + rerequestPlayingAudioWhenSignalled(playing); + stopPlayingAudio(playing); + continue; + } + + if (playing->m_status == PS_Stopped) { + continue; + } + + if (m_volumeHasChanged) + { + adjustPlayingVolume(playing); + } + + const Coord3D *pos = getCurrentPositionFromEvent(playing->m_audioEventRTS.Peek()); + if (pos) + { + if( playing->m_audioEventRTS->isDead() ) + { + stopAudioEvent( playing->m_audioEventRTS->getPlayingHandle() ); + } + else + { + Real volForConsideration = getEffectiveVolume(playing->m_audioEventRTS.Peek()); + volForConsideration /= (m_sound3DVolume > 0.0f ? m_soundVolume : 1.0f); + Bool playAnyways = BitIsSet( playing->m_audioEventRTS->getAudioEventInfo()->m_type, ST_GLOBAL) + || playing->m_audioEventRTS->getAudioEventInfo()->m_priority == AP_CRITICAL; + if( volForConsideration < m_audioSettings->m_minVolume && !playAnyways ) + { + stopPlayingAudio(playing); + } + else + { + Real x = pos->x; + Real y = pos->y; + Real z = pos->z; + DEBUG_ASSERTCRASH(playing->m_3DSample, ("3D Sample is not expected to be null")); + AIL_set_3D_position( playing->m_3DSample, x, y, z ); + } + } + } + else + { + stopPlayingAudio(playing); + } + } + + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = (*it); + + if (playing->m_status == PS_Stopping) { + rerequestPlayingAudioWhenSignalled(playing); + stopPlayingAudio(playing); + continue; + } + + if (playing->m_status == PS_Stopped) { + continue; + } + + if (m_volumeHasChanged) + { + adjustPlayingVolume(playing); + } + } + + // + // Release audio with locking. Must not call into Miles! + // + releasePlayingAudioInListIfStopped(m_playingSounds, m_playingSoundsCS); + releasePlayingAudioInListIfStopped(m_playing3DSounds, m_playing3DSoundsCS); + releasePlayingAudioInListIfStopped(m_playingStreams, m_playingStreamsCS); + + // + // Transfer streams to fade list when signaled. + // + { + CriticalSectionClass::LockClass lock(m_playingStreamsCS); + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ) { + playing = (*it); + + if (playing->m_fade) + { + { + CriticalSectionClass::LockClass lock(m_fadingAudioCS); + m_fadingAudio.push_back(playing); + } + it = m_playingStreams.erase(it); + continue; + } + + ++it; + } + } + + if (m_volumeHasChanged) { + m_volumeHasChanged = false; + + // TheSuperHackers @bugfix Push speech volume changes because Bink movie audio bypasses the Miles mixer. + if (TheVideoPlayer) { + TheVideoPlayer->setVolume(getVolume(AudioAffect_Speech)); + } + } } - //------------------------------------------------------------------------------------------------- void MilesAudioManager::processFadingList() { - std::list::iterator it; - PlayingAudio* playing; + std::list::iterator it; + PlayingAudio *playing; - // - // Stop audio without locking. Calls into Miles. - // - for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { - playing = (*it); + // + // Stop audio without locking. Calls into Miles. + // + for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ++it) { + playing = (*it); - if (playing->m_framesFaded >= getAudioSettings()->m_fadeAudioFrames) { - stopPlayingAudio(playing); - continue; - } + if (playing->m_framesFaded >= getAudioSettings()->m_fadeAudioFrames) { + stopPlayingAudio(playing); + continue; + } - if (playing->m_status == PS_Stopped) { - continue; - } + if (playing->m_status == PS_Stopped) { + continue; + } - ++playing->m_framesFaded; - Real volume = getEffectiveVolume(playing->m_audioEventRTS); - volume *= (1.0f - 1.0f * playing->m_framesFaded / getAudioSettings()->m_fadeAudioFrames); + ++playing->m_framesFaded; + Real volume = getEffectiveVolume(playing->m_audioEventRTS.Peek()); + volume *= (1.0f - 1.0f * playing->m_framesFaded / getAudioSettings()->m_fadeAudioFrames); - switch (playing->m_type) - { - case PAT_Sample: - { - AIL_set_sample_volume_pan(playing->m_sample, volume, 0.5f); - break; - } + switch(playing->m_type) + { + case PAT_Sample: + { + AIL_set_sample_volume_pan(playing->m_sample, volume, 0.5f); + break; + } - case PAT_3DSample: - { - AIL_set_3D_sample_volume(playing->m_3DSample, volume); - break; - } + case PAT_3DSample: + { + AIL_set_3D_sample_volume(playing->m_3DSample, volume); + break; + } - case PAT_Stream: - { - AIL_set_stream_volume_pan(playing->m_stream, volume, 0.5f); - break; - } - } - } + case PAT_Stream: + { + AIL_set_stream_volume_pan(playing->m_stream, volume, 0.5f); + break; + } + } + } - // - // Release audio with locking. Must not call into Miles! - // - releasePlayingAudioInListIfStopped(m_fadingAudio, m_fadingAudioCS); + // + // Release audio with locking. Must not call into Miles! + // + releasePlayingAudioInListIfStopped(m_fadingAudio, m_fadingAudioCS); } //------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::shouldProcessRequestThisFrame(AudioRequest* req) const +Bool MilesAudioManager::shouldProcessRequestThisFrame( AudioRequest *req ) const { - if (!req->m_usePendingEvent) { - return true; - } + if (req->m_pendingEvent == nullptr) { + return true; + } - if (req->m_pendingEvent->getDelay() < MSEC_PER_LOGICFRAME_REAL) { - return true; - } + if (req->m_pendingEvent->getDelay() < MSEC_PER_LOGICFRAME_REAL) { + return true; + } - return false; + return false; } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::adjustRequest(AudioRequest* req) +void MilesAudioManager::adjustRequest( AudioRequest *req ) { - if (!req->m_usePendingEvent) { - return; - } + if (req->m_pendingEvent == nullptr) { + return; + } - req->m_pendingEvent->decrementDelay(MSEC_PER_LOGICFRAME_REAL); - req->m_requiresCheckForSample = true; + req->m_pendingEvent->decrementDelay(MSEC_PER_LOGICFRAME_REAL); + req->m_requiresCheckForSample = true; } //------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::checkForSample(AudioRequest* req) +Bool MilesAudioManager::checkForSample( AudioRequest *req ) { - if (!req->m_usePendingEvent) { - return true; - } + if (req->m_pendingEvent == nullptr) { + return true; + } - if (req->m_pendingEvent->getAudioEventInfo() == nullptr) - { - // Fill in event info - getInfoForAudioEvent(req->m_pendingEvent); - } + if ( req->m_pendingEvent->getAudioEventInfo() == nullptr ) + { + // Fill in event info + getInfoForAudioEvent( req->m_pendingEvent.Peek() ); + } - if (req->m_pendingEvent->getAudioEventInfo()->m_type != AT_SoundEffect) - { - return true; - } + if (req->m_pendingEvent->getAudioEventInfo()->m_type != AT_SoundEffect) + { + return true; + } - return m_sound->canPlayNow(req->m_pendingEvent); + return m_sound->canPlayNow(req->m_pendingEvent.Peek()); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::setHardwareAccelerated(Bool accel) { - // Extends - Bool retEarly = (accel == m_hardwareAccel); - AudioManager::setHardwareAccelerated(accel); + // Extends + Bool retEarly = (accel == m_hardwareAccel); + AudioManager::setHardwareAccelerated(accel); - if (retEarly) { - return; - } + if (retEarly) { + return; + } - if (m_hardwareAccel) { - for (Int i = 0; i < MAX_HW_PROVIDERS; ++i) { - UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[i]); - TheAudio->selectProvider(providerNdx); - if (getSelectedProvider() == providerNdx) { - return; - } - } - } + if (m_hardwareAccel) { + for (Int i = 0; i < MAX_HW_PROVIDERS; ++i) { + UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[i]); + TheAudio->selectProvider(providerNdx); + if (getSelectedProvider() == providerNdx) { + return; + } + } + } - // set it false - AudioManager::setHardwareAccelerated(FALSE); - UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS]); - TheAudio->selectProvider(providerNdx); + // set it false + AudioManager::setHardwareAccelerated(FALSE); + UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS]); + TheAudio->selectProvider(providerNdx); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::setSpeakerSurround(Bool surround) { - // Extends - Bool retEarly = (surround == m_surroundSpeakers); - AudioManager::setSpeakerSurround(surround); + // Extends + Bool retEarly = (surround == m_surroundSpeakers); + AudioManager::setSpeakerSurround(surround); - if (retEarly) { - return; - } + if (retEarly) { + return; + } - UnsignedInt speakerType; - if (m_surroundSpeakers) { - speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType3D; - } - else { - speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType2D; - } + UnsignedInt speakerType; + if (m_surroundSpeakers) { + speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType3D; + } else { + speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType2D; + } - TheAudio->setSpeakerType(speakerType); + TheAudio->setSpeakerType(speakerType); } //------------------------------------------------------------------------------------------------- -Real MilesAudioManager::getFileLengthMS(AsciiString strToLoad) const +Real MilesAudioManager::getFileLengthMS( AsciiString strToLoad ) const { - if (strToLoad.isEmpty()) { - return 0.0f; - } + if (strToLoad.isEmpty()) { + return 0.0f; + } - // Load it as a stream to get the file info without actually opening the file. - HSTREAM stream = AIL_open_stream(m_digitalHandle, strToLoad.str(), 0); - if (!stream) { - return 0.0f; - } + // Load it as a stream to get the file info without actually opening the file. + HSTREAM stream = AIL_open_stream(m_digitalHandle, strToLoad.str(), 0); + if (!stream) { + return 0.0f; + } - long retVal; - AIL_stream_ms_position(stream, &retVal, nullptr); - // Now close the stream - AIL_close_stream(stream); + long retVal; + AIL_stream_ms_position(stream, &retVal, nullptr); + // Now close the stream + AIL_close_stream(stream); - return INT_TO_REAL(retVal); + return INT_TO_REAL(retVal); } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::closeAnySamplesUsingFile(const void* fileToClose) +void MilesAudioManager::closeAnySamplesUsingFile( const void *fileToClose ) { - std::list::iterator it; - PlayingAudio* playing; + std::list::iterator it; + PlayingAudio *playing; - for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - playing = *it; + for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) { + playing = *it; - if (playing->m_file == fileToClose) { - stopPlayingAudio(playing); - } - } + if (playing->m_file == fileToClose) { + stopPlayingAudio(playing); + } + } - for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) { - playing = *it; + for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) { + playing = *it; - if (playing->m_file == fileToClose) { - stopPlayingAudio(playing); - } - } + if (playing->m_file == fileToClose) { + stopPlayingAudio(playing); + } + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::setDeviceListenerPosition() { - if (m_listener) { - AIL_set_3D_orientation(m_listener, m_listenerOrientation.x, m_listenerOrientation.y, m_listenerOrientation.z, 0, 0, -1); + if (m_listener) { + AIL_set_3D_orientation(m_listener, m_listenerOrientation.x, m_listenerOrientation.y, m_listenerOrientation.z, 0, 0, -1); - Real x = m_listenerPosition.x; - Real y = m_listenerPosition.y; - Real z = m_listenerPosition.z; - AIL_set_3D_position(m_listener, x, y, z); - } + Real x = m_listenerPosition.x; + Real y = m_listenerPosition.y; + Real z = m_listenerPosition.z; + AIL_set_3D_position( m_listener, x, y, z ); + } } //------------------------------------------------------------------------------------------------- -const Coord3D* MilesAudioManager::getCurrentPositionFromEvent(AudioEventRTS* event) +const Coord3D *MilesAudioManager::getCurrentPositionFromEvent( AudioEventRTS *event ) { - if (!event->isPositionalAudio()) { - return nullptr; - } + if (!event->isPositionalAudio()) { + return nullptr; + } - return event->getCurrentPosition(); -} - -//------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::isOnScreen(const Coord3D* pos) const -{ - static ICoord2D dummy; - // WorldToScreen will return True if the point is onscreen and false if it is offscreen. - return TheTacticalView->worldToScreen(pos, &dummy); -} - -//------------------------------------------------------------------------------------------------- -Real MilesAudioManager::getEffectiveVolume(AudioEventRTS* event) const -{ - Real volume = event->getVolume() * event->getVolumeShift(); - - switch (event->getAudioEventInfo()->m_soundType) - { - case AT_Music: - { - volume *= m_musicVolume; - break; - } - case AT_Streaming: - { - volume *= m_speechVolume; - break; - } - case AT_SoundEffect: - { - if (event->isPositionalAudio()) - { - volume *= m_sound3DVolume; - const Coord3D* pos = event->getCurrentPosition(); - if (pos) - { - Coord3D distance = m_listenerPosition; - distance.sub(*pos); - Real objMinDistance; - Real objMaxDistance; + return event->getCurrentPosition(); +} - const AudioSettings* audioSettings = TheAudio->getAudioSettings(); +//------------------------------------------------------------------------------------------------- +Bool MilesAudioManager::isOnScreen( const Coord3D *pos ) const +{ + static ICoord2D dummy; + // WorldToScreen will return True if the point is onscreen and false if it is offscreen. + return TheTacticalView->worldToScreen(pos, &dummy); +} + +//------------------------------------------------------------------------------------------------- +Real MilesAudioManager::getEffectiveVolume(AudioEventRTS *event) const +{ + Real volume = event->getVolume() * event->getVolumeShift(); + + switch (event->getAudioEventInfo()->m_soundType) + { + case AT_Music: + { + volume *= m_musicVolume; + break; + } + case AT_Streaming: + { + volume *= m_speechVolume; + break; + } + case AT_SoundEffect: + { + if (event->isPositionalAudio()) + { + volume *= m_sound3DVolume; + const Coord3D *pos = event->getCurrentPosition(); + if (pos) + { + Coord3D distance = m_listenerPosition; + distance.sub(*pos); + Real objMinDistance; + Real objMaxDistance; + + const AudioSettings *audioSettings = TheAudio->getAudioSettings(); - if (event->getAudioEventInfo()->m_type & ST_GLOBAL) - { - objMinDistance = audioSettings->m_globalMinRange; - objMaxDistance = audioSettings->m_globalMaxRange; - } - else - { - objMinDistance = event->getAudioEventInfo()->m_minDistance; - objMaxDistance = event->getAudioEventInfo()->m_maxDistance; - } + if (event->getAudioEventInfo()->m_type & ST_GLOBAL) + { + objMinDistance = audioSettings->m_globalMinRange; + objMaxDistance = audioSettings->m_globalMaxRange; + } + else + { + objMinDistance = event->getAudioEventInfo()->m_minDistance; + objMaxDistance = event->getAudioEventInfo()->m_maxDistance; + } - const Real objDistance = distance.length(); + const Real objDistance = distance.length(); - if (objDistance >= objMaxDistance) - { - volume = 0.0f; - } - else if (audioSettings->m_use3DSoundRangeVolumeFade && objDistance > objMinDistance) - { - Real attenuation = (objDistance - objMinDistance) / (objMaxDistance - objMinDistance); - attenuation = pow(attenuation, audioSettings->m_3DSoundRangeVolumeFadeExponent); - volume *= 1.0f - attenuation; - } - } - } - else - { - volume *= m_soundVolume; - } - break; - } - } + if( objDistance >= objMaxDistance ) + { + volume = 0.0f; + } + else if( audioSettings->m_use3DSoundRangeVolumeFade && objDistance > objMinDistance ) + { + Real attenuation = (objDistance - objMinDistance) / (objMaxDistance - objMinDistance); + attenuation = pow(attenuation, audioSettings->m_3DSoundRangeVolumeFadeExponent); + volume *= 1.0f - attenuation; + } + } + } + else + { + volume *= m_soundVolume; + } + break; + } + } - return volume; + return volume; } //------------------------------------------------------------------------------------------------- -Bool MilesAudioManager::startNextLoop(PlayingAudio* looping) +Bool MilesAudioManager::startNextLoop( PlayingAudio *playing ) { - closeFile(looping->m_file); - looping->m_file = nullptr; + closeFile(playing->m_file); + playing->m_file = nullptr; + + if (!playing->isPlaying()) { + return false; + } + + if (playing->m_requestStop) { + return false; + } - if (looping->m_status != PS_Playing) { - return false; - } + if (playing->m_audioEventRTS->hasMoreLoops()) { + // generate a new filename, and test to see whether we can play with it now + playing->m_audioEventRTS->generateFilename(); - if (looping->m_audioEventRTS->hasMoreLoops()) { - // generate a new filename, and test to see whether we can play with it now - looping->m_audioEventRTS->generateFilename(); + if (playing->m_audioEventRTS->getDelay() > MSEC_PER_LOGICFRAME_REAL) { + playing->m_rerequestOnNextUpdate = true; + InterlockedCompareExchange(reinterpret_cast(&playing->m_status), PS_Stopping, PS_Playing); + return true; + } - if (looping->m_audioEventRTS->getDelay() > MSEC_PER_LOGICFRAME_REAL) { - // fake it out so that this sound appears done, but also so that it will not - // delete the sound on completion (which would suck) - looping->m_cleanupAudioEventRTS = false; - InterlockedCompareExchange(reinterpret_cast(&looping->m_status), PS_Stopping, PS_Playing); + if (playing->m_type == PAT_3DSample) { + playing->m_file = playSample3D(playing->m_audioEventRTS.Peek(), playing->m_3DSample); + } else { + playing->m_file = playSample(playing->m_audioEventRTS.Peek(), playing->m_sample); + } - AudioRequest* req = allocateAudioRequest(true); - req->m_pendingEvent = looping->m_audioEventRTS; - req->m_requiresCheckForSample = true; - appendAudioRequest(req); - return true; - } - - if (looping->m_type == PAT_3DSample) { - looping->m_file = playSample3D(looping->m_audioEventRTS, looping->m_3DSample); - } - else { - looping->m_file = playSample(looping->m_audioEventRTS, looping->m_sample); - } - - return looping->m_file != nullptr; - } - return false; -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::playStream(AudioEventRTS* event, HSTREAM stream) -{ - // Force it to the beginning - if (event->getAudioEventInfo()->m_soundType == AT_Music) { - AIL_set_stream_loop_count(stream, INFINITE_LOOP_COUNT); - } - - AIL_register_stream_callback(stream, setStreamCompleted); - AIL_start_stream(stream); - if (event->getAudioEventInfo()->m_soundType == AT_Music) { - // Need to stop/fade out the old music here. - } + return playing->m_file != nullptr; + } + return false; +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::playStream( AudioEventRTS *event, HSTREAM stream ) +{ + // Force it to the beginning + if (event->getAudioEventInfo()->m_soundType == AT_Music) { + AIL_set_stream_loop_count(stream, INFINITE_LOOP_COUNT); + } + + AIL_register_stream_callback(stream, setStreamCompleted); + AIL_start_stream(stream); + if (event->getAudioEventInfo()->m_soundType == AT_Music) { + // Need to stop/fade out the old music here. + } } //------------------------------------------------------------------------------------------------- -void* MilesAudioManager::playSample(AudioEventRTS* event, HSAMPLE sample) +void *MilesAudioManager::playSample( AudioEventRTS *event, HSAMPLE sample ) { - AIL_init_sample(sample); + AIL_init_sample(sample); - // Prep any sort of filtering, etc, here - AIL_register_EOS_callback(sample, setSampleCompleted); - initFilters(sample, event); + // Prep any sort of filtering, etc, here + AIL_register_EOS_callback(sample, setSampleCompleted); + initFilters(sample, event); - // Load the file in - void* fileBuffer = nullptr; - fileBuffer = loadFileForRead(event); - if (fileBuffer) { - AIL_set_sample_file(sample, fileBuffer, 0); + // Load the file in + void *fileBuffer = nullptr; + fileBuffer = loadFileForRead(event); + if (fileBuffer) { + AIL_set_sample_file(sample, fileBuffer, 0); - // Start playback - AIL_start_sample(sample); - } + // Start playback + AIL_start_sample(sample); + } - return fileBuffer; + return fileBuffer; } //------------------------------------------------------------------------------------------------- -void* MilesAudioManager::playSample3D(AudioEventRTS* event, H3DSAMPLE sample3D) +void *MilesAudioManager::playSample3D( AudioEventRTS *event, H3DSAMPLE sample3D ) { - const Coord3D* pos = getCurrentPositionFromEvent(event); - if (pos) { - // Load the file in - void* fileBuffer = loadFileForRead(event); - if (fileBuffer) { - AIL_set_3D_sample_file(sample3D, fileBuffer); + const Coord3D *pos = getCurrentPositionFromEvent(event); + if (pos) { + // Load the file in + void *fileBuffer = loadFileForRead(event); + if (fileBuffer) { + AIL_set_3D_sample_file(sample3D, fileBuffer); - // Prep any sort of filtering, etc, here - AIL_register_3D_EOS_callback(sample3D, set3DSampleCompleted); + // Prep any sort of filtering, etc, here + AIL_register_3D_EOS_callback(sample3D, set3DSampleCompleted); - // Set the position values of the sample here - if (event->getAudioEventInfo()->m_type & ST_GLOBAL) { - AIL_set_3D_sample_distances(sample3D, TheAudio->getAudioSettings()->m_globalMinRange, TheAudio->getAudioSettings()->m_globalMaxRange); - } - else { - AIL_set_3D_sample_distances(sample3D, event->getAudioEventInfo()->m_minDistance, event->getAudioEventInfo()->m_maxDistance); - } + // Set the position values of the sample here + if (event->getAudioEventInfo()->m_type & ST_GLOBAL) { + AIL_set_3D_sample_distances(sample3D, TheAudio->getAudioSettings()->m_globalMinRange, TheAudio->getAudioSettings()->m_globalMaxRange ); + } else { + AIL_set_3D_sample_distances(sample3D, event->getAudioEventInfo()->m_minDistance, event->getAudioEventInfo()->m_maxDistance ); + } - // Set the position of the sample here - Real x = pos->x; - Real y = pos->y; - Real z = pos->z; - AIL_set_3D_position(sample3D, x, y, z); - initFilters3D(sample3D, event, pos); + // Set the position of the sample here + Real x = pos->x; + Real y = pos->y; + Real z = pos->z; + AIL_set_3D_position( sample3D, x, y, z ); + initFilters3D(sample3D, event, pos); - // Start playback - AIL_start_3D_sample(sample3D); - } - return fileBuffer; - } + // Start playback + AIL_start_3D_sample(sample3D); + } + return fileBuffer; + } - return nullptr; + return nullptr; } //------------------------------------------------------------------------------------------------- void MilesAudioManager::buildProviderList() { - HPROENUM next = HPROENUM_FIRST; + HPROENUM next = HPROENUM_FIRST; - char* name; - UnsignedInt index = 0; - while (index < MAXPROVIDERS && AIL_enumerate_3D_providers(&next, &m_provider3D[index].id, &name)) { - m_provider3D[index].name.set(name); // set it to the AsciiString - ++index; - } + char *name; + UnsignedInt index = 0; + while (index < MAXPROVIDERS && AIL_enumerate_3D_providers(&next, &m_provider3D[index].id, &name)) { + m_provider3D[index].name.set(name); // set it to the AsciiString + ++index; + } - m_providerCount = index; + m_providerCount = index; } //------------------------------------------------------------------------------------------------- void MilesAudioManager::createListener() { - if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { - return; - } + if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { + return; + } - m_listener = AIL_open_3D_listener(m_provider3D[m_selectedProvider].id); - // initial listener position will be (0, 0, 0) + m_listener = AIL_open_3D_listener(m_provider3D[m_selectedProvider].id); + // initial listener position will be (0, 0, 0) } //------------------------------------------------------------------------------------------------- void MilesAudioManager::initDelayFilter() { - if (m_delayFilter != nullptr) { - return; - } + if (m_delayFilter != nullptr) { + return; + } - char* filterName; - HPROENUM enumFLTs = HPROENUM_FIRST; - HPROVIDER currentProvider; + char* filterName; + HPROENUM enumFLTs = HPROENUM_FIRST; + HPROVIDER currentProvider; - while (AIL_enumerate_filters(&enumFLTs, ¤tProvider, &filterName)) { - if (strcmp(filterName, "Mono Delay Filter") == 0) { - m_delayFilter = currentProvider; - break; - } - } + while (AIL_enumerate_filters(&enumFLTs, ¤tProvider, &filterName )) { + if (strcmp(filterName,"Mono Delay Filter") == 0) { + m_delayFilter = currentProvider; + break; + } + } } //------------------------------------------------------------------------------------------------- Bool MilesAudioManager::isValidProvider() { - return (m_selectedProvider < m_providerCount); + return (m_selectedProvider < m_providerCount); } //------------------------------------------------------------------------------------------------- void MilesAudioManager::initSamplePools() { - if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { - return; - } - - m_availableSamples.reserve(getAudioSettings()->m_sampleCount2D); - m_available3DSamples.reserve(getAudioSettings()->m_sampleCount3D); - - int i = 0; - for (i = 0; i < getAudioSettings()->m_sampleCount2D; ++i) { - HSAMPLE sample = AIL_allocate_sample_handle(m_digitalHandle); - DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 2D samples", i + 1)); - if (sample) { - AIL_init_sample(sample); - AIL_set_sample_user_data(sample, 0, (void*)(i + 1)); - m_availableSamples.push_back(sample); - ++m_num2DSamples; - } - } - - for (i = 0; i < getAudioSettings()->m_sampleCount3D; ++i) { - H3DSAMPLE sample = AIL_allocate_3D_sample_handle(m_provider3D[m_selectedProvider].id); - DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 3D samples", i + 1)); - if (sample) { - AIL_set_3D_user_data(sample, 0, (void*)(i + 1)); - m_available3DSamples.push_back(sample); - ++m_num3DSamples; - } - } - - // Streams are basically free, so we can just allocate the appropriate number - m_numStreams = getAudioSettings()->m_streamCount; -} - -//------------------------------------------------------------------------------------------------- -void MilesAudioManager::processRequest(AudioRequest* req) -{ - switch (req->m_request) - { - case AR_Play: - { - playAudioEvent(req); - break; - } - case AR_Pause: - { - pauseAudioEvent(req->m_handleToInteractOn); - break; - } - case AR_Stop: - { - stopAudioEvent(req->m_handleToInteractOn); - break; - } - } -} - -//------------------------------------------------------------------------------------------------- -void* MilesAudioManager::getHandleForBink() -{ - if (m_binkHandle == nullptr) { - PlayingAudio* aud = allocatePlayingAudio(); - aud->m_audioEventRTS = NEW AudioEventRTS("BinkHandle"); // poolify - getInfoForAudioEvent(aud->m_audioEventRTS); - aud->m_sample = getAvailable2DSample(aud->m_audioEventRTS); - aud->m_type = PAT_Sample; - - if (!aud->m_sample) { - stopPlayingAudio(aud); - releasePlayingAudio(aud); - return nullptr; - } - - m_binkHandle = aud; - } - - AILLPDIRECTSOUND lpDS; - AIL_get_DirectSound_info(m_binkHandle->m_sample, &lpDS, nullptr); - return lpDS; + if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) { + return; + } + + m_availableSamples.reserve(getAudioSettings()->m_sampleCount2D); + m_available3DSamples.reserve(getAudioSettings()->m_sampleCount3D); + + int i = 0; + for (i = 0; i < getAudioSettings()->m_sampleCount2D; ++i) { + HSAMPLE sample = AIL_allocate_sample_handle(m_digitalHandle); + DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 2D samples", i + 1)); + if (sample) { + AIL_init_sample(sample); + AIL_set_sample_user_data(sample, 0, (void *)(i + 1)); + m_availableSamples.push_back(sample); + ++m_num2DSamples; + } + } + + for (i = 0; i < getAudioSettings()->m_sampleCount3D; ++i) { + H3DSAMPLE sample = AIL_allocate_3D_sample_handle(m_provider3D[m_selectedProvider].id); + DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 3D samples", i + 1)); + if (sample) { + AIL_set_3D_user_data(sample, 0, (void *)(i + 1)); + m_available3DSamples.push_back(sample); + ++m_num3DSamples; + } + } + + // Streams are basically free, so we can just allocate the appropriate number + m_numStreams = getAudioSettings()->m_streamCount; +} + +//------------------------------------------------------------------------------------------------- +void MilesAudioManager::processRequest( AudioRequest *req ) +{ + switch (req->m_request) + { + case AR_Play: + { + playAudioEvent(req); + break; + } + case AR_Pause: + { + pauseAudioEvent(req->m_handleToInteractOn); + break; + } + case AR_Stop: + { + stopAudioEvent(req->m_handleToInteractOn); + break; + } + } +} + +//------------------------------------------------------------------------------------------------- +void *MilesAudioManager::getHandleForBink() +{ + if (m_binkHandle == nullptr) { + PlayingAudio *playing = allocatePlayingAudio(); + playing->m_audioEventRTS.Assign_No_Add_Ref(newInstance(DynamicAudioEventRTS)("BinkHandle")); + getInfoForAudioEvent(playing->m_audioEventRTS.Peek()); + playing->m_sample = getAvailable2DSample(playing->m_audioEventRTS.Peek()); + playing->m_type = PAT_Sample; + + if (!playing->m_sample) { + stopPlayingAudio(playing); + releasePlayingAudio(playing); + return nullptr; + } + + m_binkHandle = playing; + } + + AILLPDIRECTSOUND lpDS; + AIL_get_DirectSound_info(m_binkHandle->m_sample, &lpDS, nullptr); + return lpDS; } //------------------------------------------------------------------------------------------------- void MilesAudioManager::releaseHandleForBink() { - if (m_binkHandle) { - stopPlayingAudio(m_binkHandle); - releasePlayingAudio(m_binkHandle); - m_binkHandle = nullptr; - } + if (m_binkHandle) { + stopPlayingAudio(m_binkHandle); + releasePlayingAudio(m_binkHandle); + m_binkHandle = nullptr; + } } //------------------------------------------------------------------------------------------------- void MilesAudioManager::friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) { - if (!eventToPlay->getAudioEventInfo()) { - getInfoForAudioEvent(eventToPlay); - if (!eventToPlay->getAudioEventInfo()) { - DEBUG_CRASH(("No info for forced audio event '%s'", eventToPlay->getEventName().str())); - return; - } - } + if (!eventToPlay->getAudioEventInfo()) { + getInfoForAudioEvent(eventToPlay); + if (!eventToPlay->getAudioEventInfo()) { + DEBUG_CRASH(("No info for forced audio event '%s'", eventToPlay->getEventName().str())); + return; + } + } - switch (eventToPlay->getAudioEventInfo()->m_soundType) - { - case AT_Music: - if (!isOn(AudioAffect_Music)) - return; - break; - case AT_SoundEffect: - if (!isOn(AudioAffect_Sound) || !isOn(AudioAffect_Sound3D)) - return; - break; - case AT_Streaming: - if (!isOn(AudioAffect_Speech)) - return; - break; - } + switch (eventToPlay->getAudioEventInfo()->m_soundType) + { + case AT_Music: + if (!isOn(AudioAffect_Music)) + return; + break; + case AT_SoundEffect: + if (!isOn(AudioAffect_Sound) || !isOn(AudioAffect_Sound3D)) + return; + break; + case AT_Streaming: + if (!isOn(AudioAffect_Speech)) + return; + break; + } - AudioEventRTS event = *eventToPlay; + AudioEventRTS event = *eventToPlay; - event.generateFilename(); - event.generatePlayInfo(); + event.generateFilename(); + event.generatePlayInfo(); - std::list/**/>::iterator it; - for (it = m_adjustedVolumes.begin(); it != m_adjustedVolumes.end(); ++it) { - if (it->first == event.getEventName()) { - event.setVolume(it->second); - break; - } - } + std::list/**/>::iterator it; + for (it = m_adjustedVolumes.begin(); it != m_adjustedVolumes.end(); ++it) { + if (it->first == event.getEventName()) { + event.setVolume(it->second); + break; + } + } - AsciiString fileToPlay = event.getFilename(); - HAUDIO haud = AIL_quick_load_and_play(fileToPlay.str(), 1, 0); + AsciiString fileToPlay = event.getFilename(); + HAUDIO haud = AIL_quick_load_and_play(fileToPlay.str(), 1, 0); - // Even though the event type is not Speech, this is used only for mission briefings, so use the - // speech slider to adjust the volume. - // Get the volume from the event, and pass 0.5 to play the audio in the middle. (0.0 is full left, 1.0 is full right) - AIL_quick_set_volume(haud, event.getVolume() * getVolume(AudioAffect_Speech), 0.5); - m_audioForcePlayed.push_back(haud); + // Even though the event type is not Speech, this is used only for mission briefings, so use the + // speech slider to adjust the volume. + // Get the volume from the event, and pass 0.5 to play the audio in the middle. (0.0 is full left, 1.0 is full right) + AIL_quick_set_volume(haud, event.getVolume() * getVolume(AudioAffect_Speech), 0.5); + m_audioForcePlayed.push_back(haud); } //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- -void AILCALLBACK setSampleCompleted(HSAMPLE sampleCompleted) +void AILCALLBACK setSampleCompleted( HSAMPLE sampleCompleted ) { - TheAudio->notifyOfAudioCompletion((UnsignedInt)sampleCompleted, PAT_Sample); + TheAudio->notifyOfAudioCompletion((UnsignedInt) sampleCompleted, PAT_Sample); } //------------------------------------------------------------------------------------------------- -void AILCALLBACK set3DSampleCompleted(H3DSAMPLE sample3DCompleted) +void AILCALLBACK set3DSampleCompleted( H3DSAMPLE sample3DCompleted ) { - TheAudio->notifyOfAudioCompletion((UnsignedInt)sample3DCompleted, PAT_3DSample); + TheAudio->notifyOfAudioCompletion((UnsignedInt) sample3DCompleted, PAT_3DSample); } //------------------------------------------------------------------------------------------------- -void AILCALLBACK setStreamCompleted(HSTREAM streamCompleted) +void AILCALLBACK setStreamCompleted( HSTREAM streamCompleted ) { - TheAudio->notifyOfAudioCompletion((UnsignedInt)streamCompleted, PAT_Stream); + TheAudio->notifyOfAudioCompletion((UnsignedInt) streamCompleted, PAT_Stream); } //------------------------------------------------------------------------------------------------- -U32 AILCALLBACK streamingFileOpen(char const* fileName, void** file_handle) +U32 AILCALLBACK streamingFileOpen(char const *fileName, void **file_handle) { #if defined(RTS_DEBUG) - if (sizeof(U32) != sizeof(File*)) { - RELEASE_CRASH(("streamingFileOpen - This function requires work in order to compile on non 32-bit platforms.")); - } + if (sizeof(U32) != sizeof(File*)) { + RELEASE_CRASH(("streamingFileOpen - This function requires work in order to compile on non 32-bit platforms.")); + } #endif - (*file_handle) = (void*)TheFileSystem->openFile(fileName, File::READ | File::STREAMING); - return ((*file_handle) != nullptr); + (*file_handle) = (void *) TheFileSystem->openFile(fileName, File::READ | File::STREAMING); + return ((*file_handle) != nullptr); } //------------------------------------------------------------------------------------------------- -void AILCALLBACK streamingFileClose(void* fileHandle) +void AILCALLBACK streamingFileClose(void *fileHandle) { - ((File*)fileHandle)->close(); + ((File*) fileHandle)->close(); } //------------------------------------------------------------------------------------------------- -S32 AILCALLBACK streamingFileSeek(void* fileHandle, S32 offset, U32 type) +S32 AILCALLBACK streamingFileSeek(void *fileHandle, S32 offset, U32 type) { - return ((File*)fileHandle)->seek(offset, (File::seekMode)type); + return ((File*) fileHandle)->seek(offset, (File::seekMode) type); } //------------------------------------------------------------------------------------------------- -U32 AILCALLBACK streamingFileRead(void* file_handle, void* buffer, U32 bytes) +U32 AILCALLBACK streamingFileRead(void *file_handle, void *buffer, U32 bytes) { - return ((File*)file_handle)->read(buffer, bytes); + return ((File*) file_handle)->read(buffer, bytes); } //------------------------------------------------------------------------------------------------- @@ -2976,233 +3054,230 @@ U32 AILCALLBACK streamingFileRead(void* file_handle, void* buffer, U32 bytes) //------------------------------------------------------------------------------------------------- AudioFileCache::AudioFileCache() : m_maxSize(0), m_currentlyUsedSize(0), m_mutexName("AudioFileCacheMutex") { - m_mutex = CreateMutex(nullptr, FALSE, m_mutexName); + m_mutex = CreateMutex(nullptr, FALSE, m_mutexName); } //------------------------------------------------------------------------------------------------- AudioFileCache::~AudioFileCache() { - { - ScopedMutex mut(m_mutex); - - // Free all the samples that are open. - OpenFilesHashIt it; - for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { - if (it->second.m_openCount > 0) { - DEBUG_CRASH(("Sample '%s' is still playing, and we're trying to quit.", it->second.m_eventInfo->m_audioName.str())); - } - - releaseOpenAudioFile(&it->second); - // Don't erase it from the map, cause it makes this whole process way more complicated, and - // we're about to go away anyways. - } - } - - CloseHandle(m_mutex); -} - -//------------------------------------------------------------------------------------------------- -void* AudioFileCache::openFile(AudioEventRTS* eventToOpenFrom) -{ - // Protect the entire openFile function - ScopedMutex mut(m_mutex); - - AsciiString strToFind; - switch (eventToOpenFrom->getNextPlayPortion()) - { - case PP_Attack: - strToFind = eventToOpenFrom->getAttackFilename(); - break; - case PP_Sound: - strToFind = eventToOpenFrom->getFilename(); - break; - case PP_Decay: - strToFind = eventToOpenFrom->getDecayFilename(); - break; - case PP_Done: - return nullptr; - } - - OpenFilesHash::iterator it; - it = m_openFiles.find(strToFind); - - if (it != m_openFiles.end()) { - ++it->second.m_openCount; - return it->second.m_file; - } - - // Couldn't find the file, so actually open it. - File* file = TheFileSystem->openFile(strToFind.str()); - if (!file) { - DEBUG_ASSERTLOG(strToFind.isEmpty(), ("Missing Audio File: '%s'", strToFind.str())); - return nullptr; - } - - UnsignedInt fileSize = file->size(); - char* buffer = file->readEntireAndClose(); - - OpenAudioFile openedAudioFile; - openedAudioFile.m_eventInfo = eventToOpenFrom->getAudioEventInfo(); - - AILSOUNDINFO soundInfo; - AIL_WAV_info(buffer, &soundInfo); - - if (eventToOpenFrom->isPositionalAudio()) { - if (soundInfo.channels > 1) { - DEBUG_CRASH(("Requested Positional Play of audio '%s', but it is in stereo.", strToFind.str())); - delete[] buffer; - return nullptr; - } - } - - if (soundInfo.format == WAVE_FORMAT_IMA_ADPCM) { - void* decompressFileBuffer; - U32 newFileSize; - AIL_decompress_ADPCM(&soundInfo, &decompressFileBuffer, &newFileSize); - fileSize = newFileSize; - openedAudioFile.m_compressed = TRUE; - delete[] buffer; - openedAudioFile.m_file = decompressFileBuffer; - openedAudioFile.m_soundInfo = soundInfo; - openedAudioFile.m_openCount = 1; - } - else if (soundInfo.format == WAVE_FORMAT_PCM) { - openedAudioFile.m_compressed = FALSE; - openedAudioFile.m_file = buffer; - openedAudioFile.m_soundInfo = soundInfo; - openedAudioFile.m_openCount = 1; - } - else { - DEBUG_CRASH(("Unexpected compression type in '%s'", strToFind.str())); - // prevent leaks - delete[] buffer; - return nullptr; - } - - openedAudioFile.m_fileSize = fileSize; - m_currentlyUsedSize += openedAudioFile.m_fileSize; - if (m_currentlyUsedSize > m_maxSize) { - // We need to free some samples, or we're not going to be able to play this sound. - if (!freeEnoughSpaceForSample(openedAudioFile)) { - m_currentlyUsedSize -= openedAudioFile.m_fileSize; - releaseOpenAudioFile(&openedAudioFile); - return nullptr; - } - } - - m_openFiles[strToFind] = openedAudioFile; - return openedAudioFile.m_file; -} - -//------------------------------------------------------------------------------------------------- -void AudioFileCache::closeFile(void* fileToClose) -{ - if (!fileToClose) { - return; - } - - // Protect the entire closeFile function - ScopedMutex mut(m_mutex); - - OpenFilesHash::iterator it; - for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { - if (it->second.m_file == fileToClose) { - --it->second.m_openCount; - return; - } - } -} - -//------------------------------------------------------------------------------------------------- -void AudioFileCache::setMaxSize(UnsignedInt size) -{ - // Protect the function, in case we're trying to use this value elsewhere. - ScopedMutex mut(m_mutex); - - m_maxSize = size; -} - -//------------------------------------------------------------------------------------------------- -void AudioFileCache::releaseOpenAudioFile(OpenAudioFile* fileToRelease) -{ - if (fileToRelease->m_openCount > 0) { - // This thing needs to be terminated IMMEDIATELY. - TheAudio->closeAnySamplesUsingFile(fileToRelease->m_file); - } - - if (fileToRelease->m_file) { - if (fileToRelease->m_compressed) { - // Files read in via AIL_decompress_ADPCM must be freed with AIL_mem_free_lock. - AIL_mem_free_lock(fileToRelease->m_file); - } - else { - // Otherwise, we read it, we own it, blow it away. - delete[] fileToRelease->m_file; - } - fileToRelease->m_file = nullptr; - fileToRelease->m_eventInfo = nullptr; - } + { + ScopedMutex mut(m_mutex); + + // Free all the samples that are open. + OpenFilesHashIt it; + for ( it = m_openFiles.begin(); it != m_openFiles.end(); ++it ) { + if (it->second.m_openCount > 0) { + DEBUG_CRASH(("Sample '%s' is still playing, and we're trying to quit.", it->second.m_eventInfo->m_audioName.str())); + } + + releaseOpenAudioFile(&it->second); + // Don't erase it from the map, cause it makes this whole process way more complicated, and + // we're about to go away anyways. + } + } + + CloseHandle(m_mutex); +} + +//------------------------------------------------------------------------------------------------- +void *AudioFileCache::openFile( AudioEventRTS *eventToOpenFrom ) +{ + // Protect the entire openFile function + ScopedMutex mut(m_mutex); + + AsciiString strToFind; + switch (eventToOpenFrom->getNextPlayPortion()) + { + case PP_Attack: + strToFind = eventToOpenFrom->getAttackFilename(); + break; + case PP_Sound: + strToFind = eventToOpenFrom->getFilename(); + break; + case PP_Decay: + strToFind = eventToOpenFrom->getDecayFilename(); + break; + case PP_Done: + return nullptr; + } + + OpenFilesHash::iterator it; + it = m_openFiles.find(strToFind); + + if (it != m_openFiles.end()) { + ++it->second.m_openCount; + return it->second.m_file; + } + + // Couldn't find the file, so actually open it. + File *file = TheFileSystem->openFile(strToFind.str()); + if (!file) { + DEBUG_ASSERTLOG(strToFind.isEmpty(), ("Missing Audio File: '%s'", strToFind.str())); + return nullptr; + } + + UnsignedInt fileSize = file->size(); + char* buffer = file->readEntireAndClose(); + + OpenAudioFile openedAudioFile; + openedAudioFile.m_eventInfo = eventToOpenFrom->getAudioEventInfo(); + + AILSOUNDINFO soundInfo; + AIL_WAV_info(buffer, &soundInfo); + + if (eventToOpenFrom->isPositionalAudio()) { + if (soundInfo.channels > 1) { + DEBUG_CRASH(("Requested Positional Play of audio '%s', but it is in stereo.", strToFind.str())); + delete [] buffer; + return nullptr; + } + } + + if (soundInfo.format == WAVE_FORMAT_IMA_ADPCM) { + void *decompressFileBuffer; + U32 newFileSize; + AIL_decompress_ADPCM(&soundInfo, &decompressFileBuffer, &newFileSize); + fileSize = newFileSize; + openedAudioFile.m_compressed = TRUE; + delete [] buffer; + openedAudioFile.m_file = decompressFileBuffer; + openedAudioFile.m_soundInfo = soundInfo; + openedAudioFile.m_openCount = 1; + } else if (soundInfo.format == WAVE_FORMAT_PCM) { + openedAudioFile.m_compressed = FALSE; + openedAudioFile.m_file = buffer; + openedAudioFile.m_soundInfo = soundInfo; + openedAudioFile.m_openCount = 1; + } else { + DEBUG_CRASH(("Unexpected compression type in '%s'", strToFind.str())); + // prevent leaks + delete [] buffer; + return nullptr; + } + + openedAudioFile.m_fileSize = fileSize; + m_currentlyUsedSize += openedAudioFile.m_fileSize; + if (m_currentlyUsedSize > m_maxSize) { + // We need to free some samples, or we're not going to be able to play this sound. + if (!freeEnoughSpaceForSample(openedAudioFile)) { + m_currentlyUsedSize -= openedAudioFile.m_fileSize; + releaseOpenAudioFile(&openedAudioFile); + return nullptr; + } + } + + m_openFiles[strToFind] = openedAudioFile; + return openedAudioFile.m_file; +} + +//------------------------------------------------------------------------------------------------- +void AudioFileCache::closeFile( void *fileToClose ) +{ + if (!fileToClose) { + return; + } + + // Protect the entire closeFile function + ScopedMutex mut(m_mutex); + + OpenFilesHash::iterator it; + for ( it = m_openFiles.begin(); it != m_openFiles.end(); ++it ) { + if ( it->second.m_file == fileToClose ) { + --it->second.m_openCount; + return; + } + } +} + +//------------------------------------------------------------------------------------------------- +void AudioFileCache::setMaxSize( UnsignedInt size ) +{ + // Protect the function, in case we're trying to use this value elsewhere. + ScopedMutex mut(m_mutex); + + m_maxSize = size; +} + +//------------------------------------------------------------------------------------------------- +void AudioFileCache::releaseOpenAudioFile( OpenAudioFile *fileToRelease ) +{ + if (fileToRelease->m_openCount > 0) { + // This thing needs to be terminated IMMEDIATELY. + TheAudio->closeAnySamplesUsingFile(fileToRelease->m_file); + } + + if (fileToRelease->m_file) { + if (fileToRelease->m_compressed) { + // Files read in via AIL_decompress_ADPCM must be freed with AIL_mem_free_lock. + AIL_mem_free_lock(fileToRelease->m_file); + } else { + // Otherwise, we read it, we own it, blow it away. + delete [] fileToRelease->m_file; + } + fileToRelease->m_file = nullptr; + fileToRelease->m_eventInfo = nullptr; + } } //------------------------------------------------------------------------------------------------- Bool AudioFileCache::freeEnoughSpaceForSample(const OpenAudioFile& sampleThatNeedsSpace) { - Int spaceRequired = m_currentlyUsedSize - m_maxSize; - Int runningTotal = 0; - - std::list filesToClose; - // First, search for any samples that have ref counts of 0. They are low-hanging fruit, and - // should be considered immediately. - OpenFilesHashIt it; - for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { - if (it->second.m_openCount == 0) { - // This is said low-hanging fruit. - filesToClose.push_back(it->first); - - runningTotal += it->second.m_fileSize; - - if (runningTotal >= spaceRequired) { - break; - } - } - } - - // If we don't have enough space yet, then search through the events who have a count of 1 or more - // and who are lower priority than this sound. - // Mical said that at this point, sounds shouldn't care if other sounds are interruptable or not. - // Kill any files of lower priority necessary to clear our the buffer. - if (runningTotal < spaceRequired) { - for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { - if (it->second.m_openCount > 0) { - if (it->second.m_eventInfo->m_priority < sampleThatNeedsSpace.m_eventInfo->m_priority) { - filesToClose.push_back(it->first); - runningTotal += it->second.m_fileSize; - - if (runningTotal >= spaceRequired) { - break; - } - } - } - } - } - - // We weren't able to find enough sounds to truncate. Therefore, this sound is not going to play. - if (runningTotal < spaceRequired) { - return FALSE; - } - - std::list::iterator ait; - for (ait = filesToClose.begin(); ait != filesToClose.end(); ++ait) { - OpenFilesHashIt itToErase = m_openFiles.find(*ait); - if (itToErase != m_openFiles.end()) { - releaseOpenAudioFile(&itToErase->second); - m_currentlyUsedSize -= itToErase->second.m_fileSize; - m_openFiles.erase(itToErase); - } - } - - return TRUE; + Int spaceRequired = m_currentlyUsedSize - m_maxSize; + Int runningTotal = 0; + + std::list filesToClose; + // First, search for any samples that have ref counts of 0. They are low-hanging fruit, and + // should be considered immediately. + OpenFilesHashIt it; + for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { + if (it->second.m_openCount == 0) { + // This is said low-hanging fruit. + filesToClose.push_back(it->first); + + runningTotal += it->second.m_fileSize; + + if (runningTotal >= spaceRequired) { + break; + } + } + } + + // If we don't have enough space yet, then search through the events who have a count of 1 or more + // and who are lower priority than this sound. + // Mical said that at this point, sounds shouldn't care if other sounds are interruptable or not. + // Kill any files of lower priority necessary to clear our the buffer. + if (runningTotal < spaceRequired) { + for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) { + if (it->second.m_openCount > 0) { + if (it->second.m_eventInfo->m_priority < sampleThatNeedsSpace.m_eventInfo->m_priority) { + filesToClose.push_back(it->first); + runningTotal += it->second.m_fileSize; + + if (runningTotal >= spaceRequired) { + break; + } + } + } + } + } + + // We weren't able to find enough sounds to truncate. Therefore, this sound is not going to play. + if (runningTotal < spaceRequired) { + return FALSE; + } + + std::list::iterator ait; + for (ait = filesToClose.begin(); ait != filesToClose.end(); ++ait) { + OpenFilesHashIt itToErase = m_openFiles.find(*ait); + if (itToErase != m_openFiles.end()) { + releaseOpenAudioFile(&itToErase->second); + m_currentlyUsedSize -= itToErase->second.m_fileSize; + m_openFiles.erase(itToErase); + } + } + + return TRUE; } @@ -3210,63 +3285,63 @@ Bool AudioFileCache::freeEnoughSpaceForSample(const OpenAudioFile& sampleThatNee //------------------------------------------------------------------------------------------------- void MilesAudioManager::dumpAllAssetsUsed() { - if (!TheGlobalData->m_preloadReport) { - return; - } - - // Dump all the audio assets we've used. - FILE* logfile = fopen("PreloadedAssets.txt", "a+"); //append to log - if (!logfile) - return; - - std::list missingEvents; - std::list usedFiles; - - std::list::iterator lit; - - fprintf(logfile, "\nAudio Asset Report - BEGIN\n"); - { - SetAsciiStringIt it; - std::vector::iterator asIt; - for (it = m_allEventsLoaded.begin(); it != m_allEventsLoaded.end(); ++it) { - AsciiString astr = *it; - AudioEventInfo* aei = findAudioEventInfo(astr); - if (!aei) { - missingEvents.push_back(astr); - continue; - } - - for (asIt = aei->m_attackSounds.begin(); asIt != aei->m_attackSounds.end(); ++asIt) { - usedFiles.push_back(*asIt); - } - - for (asIt = aei->m_sounds.begin(); asIt != aei->m_sounds.end(); ++asIt) { - usedFiles.push_back(*asIt); - } - - for (asIt = aei->m_decaySounds.begin(); asIt != aei->m_decaySounds.end(); ++asIt) { - usedFiles.push_back(*asIt); - } - - if (!aei->m_filename.isEmpty()) { - usedFiles.push_back(aei->m_filename); - } - } - - fprintf(logfile, "\nEvents Requested that are missing information - BEGIN\n"); - for (lit = missingEvents.begin(); lit != missingEvents.end(); ++lit) { - fprintf(logfile, "%s\n", (*lit).str()); - } - fprintf(logfile, "\nEvents Requested that are missing information - END\n"); - - fprintf(logfile, "\nFiles Used - BEGIN\n"); - for (lit = usedFiles.begin(); lit != usedFiles.end(); ++lit) { - fprintf(logfile, "%s\n", (*lit).str()); - } - fprintf(logfile, "\nFiles Used - END\n"); - } - fprintf(logfile, "\nAudio Asset Report - END\n"); - fclose(logfile); - logfile = nullptr; + if (!TheGlobalData->m_preloadReport) { + return; + } + + // Dump all the audio assets we've used. + FILE *logfile=fopen("PreloadedAssets.txt","a+"); //append to log + if (!logfile) + return; + + std::list missingEvents; + std::list usedFiles; + + std::list::iterator lit; + + fprintf(logfile, "\nAudio Asset Report - BEGIN\n"); + { + SetAsciiStringIt it; + std::vector::iterator asIt; + for (it = m_allEventsLoaded.begin(); it != m_allEventsLoaded.end(); ++it) { + AsciiString astr = *it; + AudioEventInfo *aei = findAudioEventInfo(astr); + if (!aei) { + missingEvents.push_back(astr); + continue; + } + + for (asIt = aei->m_attackSounds.begin(); asIt != aei->m_attackSounds.end(); ++asIt) { + usedFiles.push_back(*asIt); + } + + for (asIt = aei->m_sounds.begin(); asIt != aei->m_sounds.end(); ++asIt) { + usedFiles.push_back(*asIt); + } + + for (asIt = aei->m_decaySounds.begin(); asIt != aei->m_decaySounds.end(); ++asIt) { + usedFiles.push_back(*asIt); + } + + if (!aei->m_filename.isEmpty()) { + usedFiles.push_back(aei->m_filename); + } + } + + fprintf(logfile, "\nEvents Requested that are missing information - BEGIN\n"); + for (lit = missingEvents.begin(); lit != missingEvents.end(); ++lit) { + fprintf(logfile, "%s\n", (*lit).str()); + } + fprintf(logfile, "\nEvents Requested that are missing information - END\n"); + + fprintf(logfile, "\nFiles Used - BEGIN\n"); + for (lit = usedFiles.begin(); lit != usedFiles.end(); ++lit) { + fprintf(logfile, "%s\n", (*lit).str()); + } + fprintf(logfile, "\nFiles Used - END\n"); + } + fprintf(logfile, "\nAudio Asset Report - END\n"); + fclose(logfile); + logfile = nullptr; } #endif diff --git a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp index ebbc91179c1..5044f077710 100644 --- a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp +++ b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp @@ -202,18 +202,40 @@ VideoStreamInterface* BinkVideoPlayer::createStream( HBINK handle ) stream->m_player = this; m_firstStream = stream; - // never let volume go to 0, as Bink will interpret that as "play at full volume". - Int mod = (Int) ((TheAudio->getVolume(AudioAffect_Speech) * 0.8f) * 100) + 1; - Int volume = (32768*mod)/100; - DEBUG_LOG(("BinkVideoPlayer::createStream() - About to set volume (%g -> %d -> %d", - TheAudio->getVolume(AudioAffect_Speech), mod, volume)); - BinkSetVolume( stream->m_handle,0, volume); - DEBUG_LOG(("BinkVideoPlayer::createStream() - set volume")); + // TheSuperHackers @bugfix BinkWait must run first or Bink ignores the initial volume. + BinkWait( stream->m_handle ); + Int volume = calculateMovieAudioVolume( TheAudio->getVolume(AudioAffect_Speech) ); + BinkSetVolume( stream->m_handle, 0, volume ); } return stream; } +//============================================================================ +// BinkVideoPlayer::calculateMovieAudioVolume +//============================================================================ + +Int BinkVideoPlayer::calculateMovieAudioVolume( Real volume ) +{ + // Never let volume go to 0, as Bink will interpret that as "play at full volume". + Int mod = (Int) ((volume * 0.8f) * 100) + 1; + return (32768*mod)/100; +} + +//============================================================================ +// BinkVideoPlayer::setVolume +//============================================================================ + +void BinkVideoPlayer::setVolume( Real volume ) +{ + // Push the new volume to every open stream's audio output. + Int binkVolume = calculateMovieAudioVolume( volume ); + for ( VideoStreamInterface* stream = firstStream(); stream != nullptr; stream = stream->next() ) + { + BinkSetVolume( static_cast( stream )->m_handle, 0, binkVolume ); + } +} + //============================================================================ // BinkVideoPlayer::open //============================================================================ diff --git a/Core/Libraries/Source/WWVegas/WWLib/WWCommon.h b/Core/Libraries/Source/WWVegas/WWLib/WWCommon.h index ef926c7bb8b..7c11f59e6b6 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/WWCommon.h +++ b/Core/Libraries/Source/WWVegas/WWLib/WWCommon.h @@ -18,6 +18,7 @@ #pragma once +#include "ref_ptr.h" #include "refcount.h" #include "STLUtils.h" #include "stringex.h" diff --git a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h index f9a57c7c1ef..f58f7b158ca 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h +++ b/Core/Libraries/Source/WWVegas/WWLib/ref_ptr.h @@ -129,15 +129,15 @@ copying. To create a RefCountPtr from a raw pointer, use the global template functions - Create_NoAddRef should be used when wrapping a pointer that has just been created with NEW - Create_NoAddRef should be used when wrapping a pointer that has been returned from a "Get" function + Create_No_Add_Ref should be used when wrapping a pointer that has just been created with NEW + Create_No_Add_Ref should be used when wrapping a pointer that has been returned from a "Get" function (the function added a reference prior to returning the pointer) - Create_AddRef should be used when wrapping a pointer that has been returned from a "Peek" function + Create_Add_Ref should be used when wrapping a pointer that has been returned from a "Peek" function (the function did not add a reference prior to returning the pointer). - Create_NoAddRef and Create_AddRef are provided to allow old code to migrate from manual reference count + Create_No_Add_Ref and Create_Add_Ref are provided to allow old code to migrate from manual reference count management to RefCountPtr. New code written with RefCountPtr should rarely if ever use - Create_NoAddRef and Create_AddRef. + Create_No_Add_Ref and Create_Add_Ref. If it is absolutely necessary to extract the raw pointer, use Peek. Peek does not add a new reference to the object. Using a Peek'd object after its RefCountPtr has gone out of scope requires @@ -217,7 +217,8 @@ class RefCountPtr // Creates a RefCountPtr and does not increment the reference counter of the passed object. // Is generally used for objects returned by operator new and "Get" functions. - static RefCountPtr Create_NoAddRef(T *t) + // Prefer using Assign_No_Add_Ref. + static RefCountPtr Create_No_Add_Ref(T *t) { WWASSERT(t == nullptr || t->Num_Refs() >= 1); return RefCountPtr(t, RefCountPtr::GET); @@ -225,13 +226,14 @@ class RefCountPtr // Creates a RefCountPtr and increments the reference counter of the passed object. // Is generally used for objects returned by "Peek" functions. - static RefCountPtr Create_AddRef(T *t) + // Prefer using Assign_Add_Ref. + static RefCountPtr Create_Add_Ref(T *t) { return RefCountPtr(t, RefCountPtr::PEEK); } RefCountPtr() - : Referent(0) + : Referent(nullptr) { } @@ -247,9 +249,9 @@ class RefCountPtr // This allows construction of the smart pointer from 0 (null) // Without allows unwanted conversions from T * (and related types, including void *) RefCountPtr(DummyPtrType * dummy) - : Referent(0) + : Referent(nullptr) { - WWASSERT(dummy == 0); + WWASSERT(dummy == nullptr); } #endif @@ -292,12 +294,41 @@ class RefCountPtr Referent->Release_Ref(); } - Referent = 0; + Referent = nullptr; return *this; } #endif + + // Assigns a pointer T and does not increment the reference counter of the passed object. + // Is generally used for objects returned by operator new and "Get" functions. + void Assign_No_Add_Ref(T *t) + { + WWASSERT(t == nullptr || t->Num_Refs() >= 1); + + if (Referent) { + Referent->Release_Ref(); + } + + Referent = t; + } + + // Assigns a pointer T and increments the reference counter of the passed object. + // Is generally used for objects returned by "Peek" functions. + void Assign_Add_Ref(T *t) + { + if (t != nullptr) { + t->Add_Ref(); + } + + if (Referent) { + Referent->Release_Ref(); + } + + Referent = t; + } + template const RefCountPtr & operator =(const RefCountPtr & rhs) { @@ -320,7 +351,6 @@ class RefCountPtr rhs.Referent->Add_Ref(); } - if (Referent) { Referent->Release_Ref(); } @@ -333,7 +363,7 @@ class RefCountPtr { if (Referent) { Referent->Release_Ref(); - Referent = 0; + Referent = nullptr; } } @@ -353,7 +383,7 @@ class RefCountPtr { if (Referent) { Referent->Release_Ref(); - Referent = 0; + Referent = nullptr; } } @@ -380,7 +410,7 @@ class RefCountPtr T * Release() { T * p = Referent; - Referent = 0; + Referent = nullptr; return p; } @@ -390,7 +420,7 @@ class RefCountPtr RefCountPtr(T * referent, ReferenceHandling reference_handling) : Referent(referent) { - if (reference_handling == PEEK && 0 != referent) { + if (reference_handling == PEEK && nullptr != referent) { referent->Add_Ref(); } } @@ -412,34 +442,46 @@ bool operator <(const RefCountPtr & lhs, const RefCountPtr & rhs) return lhs.Peek() < rhs.Peek(); } -// This comparison allows us to test our smart pointer against 0 using -// 0 == my_ptr +// This comparison allows us to test our smart pointer against null using +// nullptr == my_ptr template bool operator ==(DummyPtrType * dummy, const RefCountPtr & rhs) { - if (0 != dummy) { + if (nullptr != dummy) { WWASSERT(0); return false; } - return 0 == rhs.Peek(); + return nullptr == rhs.Peek(); } -// This comparison allows us to test our smart pointer against 0 using -// 0 != my_ptr +// This comparison allows us to test our smart pointer against null using +// nullptr != my_ptr template bool operator !=(DummyPtrType * dummy, const RefCountPtr & rhs) { - if (0 != dummy) { + if (nullptr != dummy) { WWASSERT(0); return true; } - return 0 != rhs.Peek(); + return nullptr != rhs.Peek(); } template RefCountPtr Static_Cast(const RefCountPtr & base) { - return RefCountPtr::Create_AddRef((Derived *)base.Peek()); + return RefCountPtr::Create_Add_Ref(static_cast(base.Peek())); +} + +template +RefCountPtr Create_Add_Ref(T *ptr) +{ + return RefCountPtr::Create_Add_Ref(ptr); +} + +template +RefCountPtr Create_No_Add_Ref(T *ptr) +{ + return RefCountPtr::Create_No_Add_Ref(ptr); } diff --git a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp index db006f22909..ab545a07892 100644 --- a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp +++ b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp @@ -259,7 +259,7 @@ Int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, initSubsystem(TheTerrainRoads, new TerrainRoadCollection(), "Data\\INI\\Default\\Roads.ini", "Data\\INI\\Roads.ini"); initSubsystem(TheScriptEngine, (ScriptEngine*)(new ScriptEngine())); initSubsystem(TheAudio, (AudioManager*)new MilesAudioManager()); - initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new VideoPlayer())); + initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new NullVideoPlayer())); initSubsystem(TheModuleFactory, (ModuleFactory*)(new W3DModuleFactory())); initSubsystem(TheSidesList, new SidesList()); initSubsystem(TheCaveSystem, new CaveSystem()); diff --git a/Core/Tools/W3DView/AssetInfo.cpp b/Core/Tools/W3DView/AssetInfo.cpp index 6a712d8402e..a2a73948999 100644 --- a/Core/Tools/W3DView/AssetInfo.cpp +++ b/Core/Tools/W3DView/AssetInfo.cpp @@ -52,28 +52,23 @@ AssetInfoClass::Initialize () if (m_AssetType != TypeMaterial) { // Assume we are wrapping an instance as apposed to an asset 'name'. - RenderObjClass *prender_obj = m_pRenderObj; - if (prender_obj) - prender_obj->Add_Ref(); + RefCountPtr render_obj = m_pRenderObj; // If we are wrapping an asset name, then create an instance of it. - if (prender_obj == nullptr) { - prender_obj = WW3DAssetManager::Get_Instance()->Create_Render_Obj (m_Name); + if (render_obj == nullptr) { + render_obj.Assign_No_Add_Ref (WW3DAssetManager::Get_Instance()->Create_Render_Obj (m_Name)); } - if (prender_obj != nullptr) { + if (render_obj != nullptr) { // Get the hierarchy tree for this object (if one exists) - const HTreeClass *phtree = prender_obj->Get_HTree (); + const HTreeClass *phtree = render_obj->Get_HTree (); if (phtree) { // Get the name of the hierarchy tree m_HierarchyName = phtree->Get_Name (); } } - - // Release our hold on the temporary object - REF_PTR_RELEASE (prender_obj); } } diff --git a/Core/Tools/W3DView/AssetInfo.h b/Core/Tools/W3DView/AssetInfo.h index 73875689798..cc6da52e35e 100644 --- a/Core/Tools/W3DView/AssetInfo.h +++ b/Core/Tools/W3DView/AssetInfo.h @@ -37,7 +37,6 @@ #pragma once #include "WW3D2/rendobj.h" -#include "Utils.h" #include "AssetTypes.h" @@ -58,16 +57,15 @@ class AssetInfoClass // AssetInfoClass () : m_AssetType (TypeUnknown), - m_dwUserData (0L), - m_pRenderObj (nullptr) { Initialize (); } + m_dwUserData (0L) { Initialize (); } AssetInfoClass (LPCTSTR passet_name, ASSET_TYPE type, RenderObjClass *prender_obj = nullptr, DWORD user_data = 0L) : m_Name (passet_name), m_AssetType (type), m_dwUserData (user_data), - m_pRenderObj (nullptr) { REF_PTR_SET (m_pRenderObj, prender_obj); Initialize (); } + m_pRenderObj (Create_Add_Ref (prender_obj)) { Initialize (); } - virtual ~AssetInfoClass () { REF_PTR_RELEASE (m_pRenderObj); } + virtual ~AssetInfoClass () {} ////////////////////////////////////////////////////////////// // @@ -83,14 +81,14 @@ class AssetInfoClass ASSET_TYPE Get_Type () const { return m_AssetType; } DWORD Get_User_Number () const { return m_dwUserData; } const CString & Get_User_String () const { return m_UserString; } - RenderObjClass * Get_Render_Obj () const { if (m_pRenderObj) m_pRenderObj->Add_Ref(); return m_pRenderObj; } - RenderObjClass * Peek_Render_Obj () const { return m_pRenderObj; } + RenderObjClass * Get_Render_Obj () const { RenderObjClass *ptr = m_pRenderObj.Peek(); if (ptr) ptr->Add_Ref(); return ptr; } + RenderObjClass * Peek_Render_Obj () const { return m_pRenderObj.Peek(); } void Set_Name (LPCTSTR pname) { m_Name = pname; } void Set_Hierarchy_Name (LPCTSTR pname) { m_HierarchyName = pname; } void Set_Type (ASSET_TYPE type) { m_AssetType = type; } void Set_User_Number (DWORD user_data) { m_dwUserData = user_data; } void Set_User_String (LPCTSTR string) { m_UserString = string; } - void Set_Render_Obj (RenderObjClass *pobj) { REF_PTR_SET (m_pRenderObj, pobj); } + void Set_Render_Obj (RenderObjClass *pobj) { m_pRenderObj.Assign_Add_Ref (pobj); } // // Information methods @@ -118,5 +116,5 @@ class AssetInfoClass CString m_OriginalName; ASSET_TYPE m_AssetType; DWORD m_dwUserData; - RenderObjClass * m_pRenderObj; + RefCountPtr m_pRenderObj; }; diff --git a/Core/Tools/W3DView/GraphicView.cpp b/Core/Tools/W3DView/GraphicView.cpp index d2fcaa341cf..a15dd58cbbe 100644 --- a/Core/Tools/W3DView/GraphicView.cpp +++ b/Core/Tools/W3DView/GraphicView.cpp @@ -71,7 +71,6 @@ IMPLEMENT_DYNCREATE(CGraphicView, CView) //////////////////////////////////////////////////////////////////////////// CGraphicView::CGraphicView () : m_bInitialized (FALSE), - m_pCamera (nullptr), m_TimerID (0), m_bMouseDown (FALSE), m_bRMouseDown (FALSE), @@ -83,7 +82,6 @@ CGraphicView::CGraphicView () m_objectRotation (NoRotation), m_LightRotation (NoRotation), m_bLightMeshInScene (false), - m_pLightMesh (nullptr), m_ParticleCountUpdate (0), m_CameraBonePosX (false), m_UpdateCounter (0), @@ -212,7 +210,7 @@ CGraphicView::InitializeGraphicView () if (bReturn && (m_pCamera == nullptr)) { // Instantiate a new camera class - m_pCamera = new CameraClass (); + m_pCamera.Assign_No_Add_Ref (new CameraClass ()); bReturn = (m_pCamera != nullptr); // Were we successful in creating a camera? @@ -230,7 +228,7 @@ CGraphicView::InitializeGraphicView () // // Attach the 'listener' to the camera // - WWAudioClass::Get_Instance ()->Get_Sound_Scene ()->Attach_Listener_To_Obj (m_pCamera); + WWAudioClass::Get_Instance ()->Get_Sound_Scene ()->Attach_Listener_To_Obj (m_pCamera.Peek()); } Reset_FOV (); @@ -240,7 +238,7 @@ CGraphicView::InitializeGraphicView () ResourceFileClass light_mesh_file (nullptr, "Light.w3d"); WW3DAssetManager::Get_Instance()->Load_3D_Assets (light_mesh_file); - m_pLightMesh = WW3DAssetManager::Get_Instance()->Create_Render_Obj ("LIGHT"); + m_pLightMesh.Assign_No_Add_Ref (WW3DAssetManager::Get_Instance()->Create_Render_Obj ("LIGHT")); ASSERT (m_pLightMesh != nullptr); m_bLightMeshInScene = false; } @@ -323,8 +321,8 @@ CGraphicView::OnDestroy () // // Free the camera object // - REF_PTR_RELEASE (m_pCamera); - REF_PTR_RELEASE (m_pLightMesh); + m_pCamera.Clear(); + m_pLightMesh.Clear(); // Is there an update thread running? if (m_TimerID == 0) { @@ -520,7 +518,7 @@ CGraphicView::RepaintView // Wait for all previous rendering to complete before starting benchmark. DWORD profile_time = ::Get_CPU_Clock (pt_high); - WW3D::Render (doc->GetScene (), m_pCamera, FALSE, FALSE); + WW3D::Render (doc->GetScene (), m_pCamera.Peek(), FALSE, FALSE); // Wait for all rendering to complete before stopping benchmark. DWORD milliseconds = (::Get_CPU_Clock (pt_high) - profile_time) / 1000; @@ -531,7 +529,7 @@ CGraphicView::RepaintView WW3D::Render (doc->GetCursorScene (), doc->Get2DCamera (), FALSE, FALSE); // Render the dazzles - doc->Render_Dazzles(m_pCamera); + doc->Render_Dazzles(m_pCamera.Peek()); // Finish out the rendering process WW3D::End_Render (); @@ -589,7 +587,7 @@ CGraphicView::UpdateDisplay () // Render the current view inside the frame WW3D::Begin_Render (TRUE, TRUE, Vector3 (0.2,0.4,0.6)); - WW3D::Render (doc->GetScene (), m_pCamera, FALSE, FALSE); + WW3D::Render (doc->GetScene (), m_pCamera.Peek(), FALSE, FALSE); WW3D::End_Render (); } */ } diff --git a/Core/Tools/W3DView/GraphicView.h b/Core/Tools/W3DView/GraphicView.h index 43c891df881..7175327089c 100644 --- a/Core/Tools/W3DView/GraphicView.h +++ b/Core/Tools/W3DView/GraphicView.h @@ -170,7 +170,7 @@ class CGraphicView : public CView void SetAllowedCameraRotation (CAMERA_ROTATION cameraRotation); CAMERA_ROTATION GetAllowedCameraRotation () const { return m_allowedCameraRotation; } void SetCameraPos (CAMERA_POS cameraPos); - class CameraClass *GetCamera () const { return m_pCamera; } + class CameraClass *GetCamera () const { return m_pCamera.Peek(); } float Get_Camera_Distance () const { return m_CameraDistance; } void Set_Camera_Distance (float dist); @@ -200,7 +200,7 @@ class CGraphicView : public CView // // Misc // - RenderObjClass * Get_Light_Mesh () const { return m_pLightMesh; } + RenderObjClass * Get_Light_Mesh () const { return m_pLightMesh.Peek(); } Vector3 & Get_Object_Center () { return m_ObjectCenter; } // @@ -227,8 +227,8 @@ class CGraphicView : public CView BOOL m_bInitialized; BOOL m_bActive; UINT m_TimerID; - CameraClass * m_pCamera; - RenderObjClass * m_pLightMesh; + RefCountPtr m_pCamera; + RefCountPtr m_pLightMesh; bool m_bLightMeshInScene; Vector3 m_ObjectCenter; SphereClass m_ViewedSphere; diff --git a/Core/Tools/W3DView/PlaySoundDialog.cpp b/Core/Tools/W3DView/PlaySoundDialog.cpp index 06b6f2c441e..ef3d5544f7f 100644 --- a/Core/Tools/W3DView/PlaySoundDialog.cpp +++ b/Core/Tools/W3DView/PlaySoundDialog.cpp @@ -39,7 +39,6 @@ static char THIS_FILE[] = __FILE__; ///////////////////////////////////////////////////////////////////////////// PlaySoundDialogClass::PlaySoundDialogClass(LPCTSTR filename, CWnd* pParent /*=nullptr*/) : Filename (filename), - SoundObj (nullptr), CDialog(PlaySoundDialogClass::IDD, pParent) { //{{AFX_DATA_INIT(PlaySoundDialogClass) @@ -96,7 +95,7 @@ void PlaySoundDialogClass::OnCancel () { SoundObj->Stop (); - REF_PTR_RELEASE (SoundObj); + SoundObj.Clear(); CDialog::OnCancel (); } @@ -120,7 +119,7 @@ PlaySoundDialogClass::OnInitDialog () // // Create the sound effect so we can play it // - SoundObj = WWAudioClass::Get_Instance ()->Create_Sound_Effect (Filename); + SoundObj.Assign_No_Add_Ref (WWAudioClass::Get_Instance ()->Create_Sound_Effect (Filename)); if (SoundObj == nullptr) { CString message; message.Format ("Cannot find sound file: %s!", (LPCTSTR)Filename, MB_OK); diff --git a/Core/Tools/W3DView/PlaySoundDialog.h b/Core/Tools/W3DView/PlaySoundDialog.h index 31472f71e2a..1162955df3b 100644 --- a/Core/Tools/W3DView/PlaySoundDialog.h +++ b/Core/Tools/W3DView/PlaySoundDialog.h @@ -61,7 +61,7 @@ class PlaySoundDialogClass : public CDialog private: CString Filename; - AudibleSoundClass * SoundObj; + RefCountPtr SoundObj; }; //{{AFX_INSERT_LOCATION}} diff --git a/Core/Tools/W3DView/RingPropertySheet.cpp b/Core/Tools/W3DView/RingPropertySheet.cpp index 891814b89e1..6df83a97df4 100644 --- a/Core/Tools/W3DView/RingPropertySheet.cpp +++ b/Core/Tools/W3DView/RingPropertySheet.cpp @@ -48,10 +48,9 @@ RingPropertySheetClass::RingPropertySheetClass CWnd * pParentWnd, UINT iSelectPage ) - : m_RenderObj (nullptr), - CPropertySheet(nIDCaption, pParentWnd, iSelectPage) + : CPropertySheet(nIDCaption, pParentWnd, iSelectPage), + m_RenderObj (Create_Add_Ref (ring)) { - REF_PTR_SET (m_RenderObj, ring); Initialize (); } @@ -68,10 +67,9 @@ RingPropertySheetClass::RingPropertySheetClass CWnd * pParentWnd, UINT iSelectPage ) - : m_RenderObj (nullptr), - CPropertySheet(pszCaption, pParentWnd, iSelectPage) + : CPropertySheet(pszCaption, pParentWnd, iSelectPage), + m_RenderObj (Create_Add_Ref (ring)) { - REF_PTR_SET (m_RenderObj, ring); Initialize (); } @@ -83,7 +81,6 @@ RingPropertySheetClass::RingPropertySheetClass ///////////////////////////////////////////////////////////////////////////// RingPropertySheetClass::~RingPropertySheetClass () { - REF_PTR_RELEASE (m_RenderObj); } @@ -180,7 +177,7 @@ RingPropertySheetClass::Add_Object_To_Viewer () // // Create a new prototype for this object // - RingPrototypeClass *prototype = new RingPrototypeClass (m_RenderObj); + RingPrototypeClass *prototype = new RingPrototypeClass (m_RenderObj.Peek()); // // Update the asset manager with the new prototype @@ -201,14 +198,14 @@ RingPropertySheetClass::Add_Object_To_Viewer () // doc->Reload_Displayed_Object (); m_LastSavedName = m_RenderObj->Get_Name (); - REF_PTR_SET (m_RenderObj, (RingRenderObjClass *)doc->GetDisplayedObject ()); + m_RenderObj.Assign_Add_Ref ((RingRenderObjClass *)doc->GetDisplayedObject ()); // // Pass the object along to the pages // - m_GeneralPage.Set_Ring (m_RenderObj); - m_ColorPage.Set_Ring (m_RenderObj); - m_ScalePage.Set_Ring (m_RenderObj); + m_GeneralPage.Set_Ring (m_RenderObj.Peek()); + m_ColorPage.Set_Ring (m_RenderObj.Peek()); + m_ScalePage.Set_Ring (m_RenderObj.Peek()); } } @@ -242,9 +239,9 @@ RingPropertySheetClass::Initialize () // // Pass the object along to the pages // - m_GeneralPage.Set_Ring (m_RenderObj); - m_ColorPage.Set_Ring (m_RenderObj); - m_ScalePage.Set_Ring (m_RenderObj); + m_GeneralPage.Set_Ring (m_RenderObj.Peek()); + m_ColorPage.Set_Ring (m_RenderObj.Peek()); + m_ScalePage.Set_Ring (m_RenderObj.Peek()); // // Add the pages to the sheet @@ -270,12 +267,12 @@ RingPropertySheetClass::Initialize () void RingPropertySheetClass::Create_New_Object () { - m_RenderObj = new RingRenderObjClass; + m_RenderObj.Assign_No_Add_Ref (new RingRenderObjClass); m_RenderObj->Set_Name ("Ring"); // // Display the new object // - ::GetCurrentDocument ()->DisplayObject (m_RenderObj); + ::GetCurrentDocument ()->DisplayObject (m_RenderObj.Peek()); } diff --git a/Core/Tools/W3DView/RingPropertySheet.h b/Core/Tools/W3DView/RingPropertySheet.h index 1ed8f9c9570..4e101da0baf 100644 --- a/Core/Tools/W3DView/RingPropertySheet.h +++ b/Core/Tools/W3DView/RingPropertySheet.h @@ -109,7 +109,7 @@ class RingPropertySheetClass : public CPropertySheet RingGeneralPropPageClass m_GeneralPage; RingColorPropPageClass m_ColorPage; RingSizePropPageClass m_ScalePage; - RingRenderObjClass * m_RenderObj; + RefCountPtr m_RenderObj; CString m_LastSavedName; }; diff --git a/Core/Tools/W3DView/ScreenCursor.cpp b/Core/Tools/W3DView/ScreenCursor.cpp index 25d97e94d6c..8c358221e59 100644 --- a/Core/Tools/W3DView/ScreenCursor.cpp +++ b/Core/Tools/W3DView/ScreenCursor.cpp @@ -53,8 +53,6 @@ /////////////////////////////////////////////////////////////////// ScreenCursorClass::ScreenCursorClass () : m_ScreenPos (0, 0), - m_pTexture (nullptr), - m_pVertMaterial (nullptr), m_Width (0), m_Height (0), m_hWnd (nullptr) @@ -70,9 +68,7 @@ ScreenCursorClass::ScreenCursorClass () /////////////////////////////////////////////////////////////////// ScreenCursorClass::ScreenCursorClass (const ScreenCursorClass &src) : m_ScreenPos (0, 0), - m_pTexture (nullptr), m_hWnd (nullptr), - m_pVertMaterial (nullptr), m_Width (0), m_Height (0), RenderObjClass (src) @@ -88,8 +84,6 @@ ScreenCursorClass::ScreenCursorClass (const ScreenCursorClass &src) /////////////////////////////////////////////////////////////////// ScreenCursorClass::~ScreenCursorClass () { - REF_PTR_RELEASE (m_pTexture); - REF_PTR_RELEASE (m_pVertMaterial); } @@ -101,10 +95,8 @@ ScreenCursorClass::~ScreenCursorClass () void ScreenCursorClass::Initialize () { - REF_PTR_RELEASE(m_pVertMaterial); - // Create default vertex material - m_pVertMaterial = NEW_REF( VertexMaterialClass, ()); + m_pVertMaterial.Assign_No_Add_Ref (NEW_REF( VertexMaterialClass, ())); m_pVertMaterial->Set_Diffuse (1.0F, 1.0F, 1.0F); m_pVertMaterial->Set_Emissive (0.0F, 0.0F, 0.0F); m_pVertMaterial->Set_Specular (1.0F, 1.0F, 1.0F); @@ -149,7 +141,7 @@ ScreenCursorClass::Initialize () void ScreenCursorClass::Set_Texture (TextureClass *texture) { - REF_PTR_SET (m_pTexture, texture); + m_pTexture.Assign_Add_Ref (texture); // Find the dimensions of the texture: if (m_pTexture != nullptr) { @@ -296,9 +288,9 @@ ScreenCursorClass::Render (RenderInfoClass &rinfo) /* ** Apply the shader and material */ - DX8Wrapper::Set_Material(m_pVertMaterial); + DX8Wrapper::Set_Material(m_pVertMaterial.Peek()); DX8Wrapper::Set_Shader(ShaderClass::_PresetATestBlend2DShader); - DX8Wrapper::Set_Texture(0,m_pTexture); + DX8Wrapper::Set_Texture(0,m_pTexture.Peek()); DX8Wrapper::Set_Vertex_Buffer(vbaccess); DX8Wrapper::Set_Index_Buffer(ibaccess,0); diff --git a/Core/Tools/W3DView/ScreenCursor.h b/Core/Tools/W3DView/ScreenCursor.h index 937cd462e1e..19f65a6f904 100644 --- a/Core/Tools/W3DView/ScreenCursor.h +++ b/Core/Tools/W3DView/ScreenCursor.h @@ -93,8 +93,8 @@ class ScreenCursorClass : public RenderObjClass //////////////////////////////////////////////////////////////////////// HWND m_hWnd; Vector2 m_ScreenPos; - TextureClass * m_pTexture; - VertexMaterialClass *m_pVertMaterial; + RefCountPtr m_pTexture; + RefCountPtr m_pVertMaterial; Vector3 m_Verticies[4]; Vector3 m_Normals[4]; diff --git a/Core/Tools/W3DView/SpherePropertySheet.cpp b/Core/Tools/W3DView/SpherePropertySheet.cpp index 656b994fed4..07f05bcaa01 100644 --- a/Core/Tools/W3DView/SpherePropertySheet.cpp +++ b/Core/Tools/W3DView/SpherePropertySheet.cpp @@ -48,10 +48,9 @@ SpherePropertySheetClass::SpherePropertySheetClass CWnd * pParentWnd, UINT iSelectPage ) - : m_RenderObj (nullptr), - CPropertySheet(nIDCaption, pParentWnd, iSelectPage) + : CPropertySheet(nIDCaption, pParentWnd, iSelectPage), + m_RenderObj (Create_Add_Ref (sphere)) { - REF_PTR_SET (m_RenderObj, sphere); Initialize (); } @@ -68,10 +67,9 @@ SpherePropertySheetClass::SpherePropertySheetClass CWnd * pParentWnd, UINT iSelectPage ) - : m_RenderObj (nullptr), - CPropertySheet(pszCaption, pParentWnd, iSelectPage) + : CPropertySheet(pszCaption, pParentWnd, iSelectPage), + m_RenderObj (Create_Add_Ref (sphere)) { - REF_PTR_SET (m_RenderObj, sphere); Initialize (); } @@ -83,7 +81,6 @@ SpherePropertySheetClass::SpherePropertySheetClass ///////////////////////////////////////////////////////////////////////////// SpherePropertySheetClass::~SpherePropertySheetClass () { - REF_PTR_RELEASE (m_RenderObj); } @@ -180,7 +177,7 @@ SpherePropertySheetClass::Add_Object_To_Viewer () // // Create a new prototype for this object // - SpherePrototypeClass *prototype = new SpherePrototypeClass (m_RenderObj); + SpherePrototypeClass *prototype = new SpherePrototypeClass (m_RenderObj.Peek()); // // Update the asset manager with the new prototype @@ -201,14 +198,14 @@ SpherePropertySheetClass::Add_Object_To_Viewer () // doc->Reload_Displayed_Object (); m_LastSavedName = m_RenderObj->Get_Name (); - REF_PTR_SET (m_RenderObj, (SphereRenderObjClass *)doc->GetDisplayedObject ()); + m_RenderObj.Assign_Add_Ref ((SphereRenderObjClass *)doc->GetDisplayedObject ()); // // Pass the object along to the pages // - m_GeneralPage.Set_Sphere (m_RenderObj); - m_ColorPage.Set_Sphere (m_RenderObj); - m_ScalePage.Set_Sphere (m_RenderObj); + m_GeneralPage.Set_Sphere (m_RenderObj.Peek()); + m_ColorPage.Set_Sphere (m_RenderObj.Peek()); + m_ScalePage.Set_Sphere (m_RenderObj.Peek()); } } @@ -242,9 +239,9 @@ SpherePropertySheetClass::Initialize () // // Pass the object along to the pages // - m_GeneralPage.Set_Sphere (m_RenderObj); - m_ColorPage.Set_Sphere (m_RenderObj); - m_ScalePage.Set_Sphere (m_RenderObj); + m_GeneralPage.Set_Sphere (m_RenderObj.Peek()); + m_ColorPage.Set_Sphere (m_RenderObj.Peek()); + m_ScalePage.Set_Sphere (m_RenderObj.Peek()); // // Add the pages to the sheet @@ -270,12 +267,12 @@ SpherePropertySheetClass::Initialize () void SpherePropertySheetClass::Create_New_Object () { - m_RenderObj = new SphereRenderObjClass; + m_RenderObj.Assign_No_Add_Ref (new SphereRenderObjClass); m_RenderObj->Set_Name ("Sphere"); // // Display the new object // - ::GetCurrentDocument ()->DisplayObject (m_RenderObj); + ::GetCurrentDocument ()->DisplayObject (m_RenderObj.Peek()); } diff --git a/Core/Tools/W3DView/SpherePropertySheet.h b/Core/Tools/W3DView/SpherePropertySheet.h index b04e35d87af..2589687b2a3 100644 --- a/Core/Tools/W3DView/SpherePropertySheet.h +++ b/Core/Tools/W3DView/SpherePropertySheet.h @@ -109,7 +109,7 @@ class SpherePropertySheetClass : public CPropertySheet SphereGeneralPropPageClass m_GeneralPage; SphereColorPropPageClass m_ColorPage; SphereSizePropPageClass m_ScalePage; - SphereRenderObjClass * m_RenderObj; + RefCountPtr m_RenderObj; CString m_LastSavedName; }; diff --git a/Core/Tools/W3DView/W3DViewDoc.cpp b/Core/Tools/W3DView/W3DViewDoc.cpp index 4cdb0d23a5a..25213270260 100644 --- a/Core/Tools/W3DView/W3DViewDoc.cpp +++ b/Core/Tools/W3DView/W3DViewDoc.cpp @@ -129,7 +129,6 @@ CW3DViewDoc::CW3DViewDoc () CW3DViewDoc::~CW3DViewDoc () { CleanupResources (); - REF_PTR_RELEASE (m_pCursor); } @@ -141,109 +140,66 @@ CW3DViewDoc::~CW3DViewDoc () void CW3DViewDoc::CleanupResources () { - if (m_pC2DScene) + if (m_pCBackgroundBMP) { - if (m_pCBackgroundBMP) - { - // Remove the background BMP from the scene - m_pCBackgroundBMP->Remove (); - } - - // Release the 2D scene we allocated to display background BMPs - m_pC2DScene->Release_Ref (); - m_pC2DScene = nullptr; + // Remove the background BMP from the scene + m_pCBackgroundBMP->Remove (); } - if (m_pCBackObjectScene) - { - if (m_pCBackgroundObject) - { - // Remove the background BMP from the scene - m_pCBackgroundObject->Remove (); - } + // Release the 2D scene we allocated to display background BMPs + m_pC2DScene.Clear (); - // Release the scene we allocated to display background objects - m_pCBackObjectScene->Release_Ref (); - m_pCBackObjectScene = nullptr; + if (m_pCBackgroundObject) + { + // Remove the background BMP from the scene + m_pCBackgroundObject->Remove (); } + // Release the scene we allocated to display background objects + m_pCBackObjectScene.Clear (); + if (m_pCursor != nullptr) { m_pCursor->Remove (); } - REF_PTR_RELEASE (m_pCursorScene); + m_pCursorScene.Clear(); if (m_pCScene) { if (m_pCRenderObj) { // Remove the currently displayed object from the scene - Remove_Object_From_Scene (m_pCRenderObj); + Remove_Object_From_Scene (m_pCRenderObj.Peek()); } if (m_pCSceneLight) { // Remove the light from the scene - Remove_Object_From_Scene (m_pCSceneLight); + Remove_Object_From_Scene (m_pCSceneLight.Peek()); } // Get rid of the lined up objects. m_pCScene->Clear_Lineup(); // Release the scene object we allocated earlier - m_pCScene->Release_Ref (); - m_pCScene = nullptr; + m_pCScene.Clear (); } // Was there a dazzle layer? delete m_pDazzleLayer; m_pDazzleLayer = nullptr; - // Was there a valid scene object? - if (m_pCBackObjectScene) - { - // Free the scene object - m_pCBackObjectScene->Release_Ref (); - m_pCBackObjectScene = nullptr; - } - - // Was there a valid 2D camera? - if (m_pC2DCamera) - { - // Free the camera object - m_pC2DCamera->Release_Ref (); - m_pC2DCamera = nullptr; - } - - // Was there a valid background camera? - if (m_pCBackObjectCamera) - { - // Free the camera object - m_pCBackObjectCamera->Release_Ref (); - m_pCBackObjectCamera = nullptr; - } - - // Was there a valid background BMP? - if (m_pCBackgroundBMP) - { - m_pCBackgroundBMP->Release_Ref (); - m_pCBackgroundBMP = nullptr; - } + // Free the camera objects + m_pC2DCamera.Clear (); + m_pCBackObjectCamera.Clear (); - // Was there a valid scene light? - if (m_pCSceneLight) - { - m_pCSceneLight->Release_Ref (); - m_pCSceneLight = nullptr; - } + // Free the background BMP and scene light + m_pCBackgroundBMP.Clear (); + m_pCSceneLight.Clear (); - // Was there a valid display object? - if (m_pCRenderObj) - { - // Free the currently displayed object - SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); - REF_PTR_RELEASE (m_pCRenderObj); - } + // Free the currently displayed object + SAFE_DELETE (m_pCAnimCombo); + m_pCAnimation.Clear (); + m_pCRenderObj.Clear (); } /////////////////////////////////////////////////////////////// @@ -264,7 +220,7 @@ CW3DViewDoc::OnNewDocument () if (m_pCScene && m_pCRenderObj) { // Remove the currently displayed object from the scene - Remove_Object_From_Scene (m_pCRenderObj); + Remove_Object_From_Scene (m_pCRenderObj.Peek()); } if (m_pCScene) @@ -276,13 +232,10 @@ CW3DViewDoc::OnNewDocument () m_pCScene->Set_Fog_Color(m_backgroundColor); } - if (m_pCRenderObj) - { - // Free the currently displayed object - SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); - REF_PTR_RELEASE (m_pCRenderObj); - } + // Free the currently displayed object + SAFE_DELETE (m_pCAnimCombo); + m_pCAnimation.Clear(); + m_pCRenderObj.Clear(); CDataTreeView *pCDataTreeView = GetDataTreeView (); if (pCDataTreeView) @@ -354,7 +307,7 @@ CW3DViewDoc::InitScene () // ParticleEmitterClass::Set_Default_Remove_On_Complete (false); - m_pCScene = new ViewerSceneClass; + m_pCScene.Assign_No_Add_Ref (new ViewerSceneClass); ASSERT (m_pCScene); if (m_pCScene != nullptr) { @@ -365,7 +318,7 @@ CW3DViewDoc::InitScene () m_pCScene->Set_Fog_Color(GetBackgroundColor()); // Create a new scene light - m_pCSceneLight = new LightClass; + m_pCSceneLight.Assign_No_Add_Ref (new LightClass); ASSERT (m_pCSceneLight); if (m_pCSceneLight != nullptr) { @@ -381,23 +334,23 @@ CW3DViewDoc::InitScene () m_pCSceneLight->Set_Specular (Vector3(1, 1, 1)); // Add this light to the scene - m_pCScene->Add_Render_Object (m_pCSceneLight); + m_pCScene->Add_Render_Object (m_pCSceneLight.Peek()); } } // Instantiate a new 2D scene - m_pC2DScene = new SimpleSceneClass; + m_pC2DScene.Assign_No_Add_Ref (new SimpleSceneClass); ASSERT (m_pC2DScene); // Instantiate a new 2D cursor scene - m_pCursorScene = new SimpleSceneClass; - ASSERT (m_pCursorScene); + m_pCursorScene.Assign_No_Add_Ref (new SimpleSceneClass); + ASSERT (m_pCursorScene != nullptr); Create_Cursor (); - m_pCursorScene->Add_Render_Object (m_pCursor); + m_pCursorScene->Add_Render_Object (m_pCursor.Peek()); - m_pCBackObjectScene = new SimpleSceneClass; + m_pCBackObjectScene.Assign_No_Add_Ref (new SimpleSceneClass); // Were we successful in instantiating the scene object? ASSERT (m_pCBackObjectScene); @@ -410,7 +363,7 @@ CW3DViewDoc::InitScene () // Create a new instance of the camera class to use // when rendering the background object - m_pCBackObjectCamera = new CameraClass (); + m_pCBackObjectCamera.Assign_No_Add_Ref (new CameraClass ()); // Were we successful in creating the new instance? ASSERT (m_pCBackObjectCamera); @@ -424,7 +377,7 @@ CW3DViewDoc::InitScene () // Create a new instance of the camera class to use // when rendering the background BMP - m_pC2DCamera = new CameraClass (); + m_pC2DCamera.Assign_No_Add_Ref (new CameraClass ()); // Were we successful in creating the new instance? ASSERT (m_pC2DCamera); @@ -600,14 +553,13 @@ CW3DViewDoc::Display_Emitter // Lose the animation SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); + m_pCAnimation.Clear(); if (m_pCRenderObj != nullptr) { // Remove this object from the scene - Remove_Object_From_Scene (m_pCRenderObj); - m_pCRenderObj->Release_Ref (); - m_pCRenderObj = nullptr; + Remove_Object_From_Scene (m_pCRenderObj.Peek()); + m_pCRenderObj.Clear(); } m_pCScene->Clear_Lineup(); @@ -616,8 +568,8 @@ CW3DViewDoc::Display_Emitter // Add the emitter to the scene pemitter->Set_Transform (Matrix3D (1)); - REF_PTR_SET (m_pCRenderObj, pemitter); - m_pCScene->Add_Render_Object (m_pCRenderObj); + m_pCRenderObj.Assign_Add_Ref (pemitter); + m_pCScene->Add_Render_Object (m_pCRenderObj.Peek()); pemitter->Start (); CGraphicView *pCGraphicView = GetGraphicView (); @@ -657,16 +609,15 @@ CW3DViewDoc::DisplayObject { // Lose the animation SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); + m_pCAnimation.Clear(); // Do we have an old object to remove from the scene? if (add_ghost == false) { if (m_pCRenderObj) { // Remove this object from the scene - Remove_Object_From_Scene (m_pCRenderObj); - m_pCRenderObj->Release_Ref (); - m_pCRenderObj = nullptr; + Remove_Object_From_Scene (m_pCRenderObj.Peek()); + m_pCRenderObj.Clear(); } } m_pCScene->Clear_Lineup(); @@ -677,21 +628,20 @@ CW3DViewDoc::DisplayObject // Reset the animation for this object pCModel->Set_Animation (); - m_pCRenderObj = pCModel; - m_pCRenderObj->Add_Ref (); + m_pCRenderObj.Assign_Add_Ref (pCModel); m_pCRenderObj->Set_Transform (Matrix3D (1)); // Add this object to the scene if (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_BITMAP2D) { - m_pC2DScene->Add_Render_Object (m_pCRenderObj); + m_pC2DScene->Add_Render_Object (m_pCRenderObj.Peek()); } else { - m_pCScene->Add_Render_Object (m_pCRenderObj); + m_pCScene->Add_Render_Object (m_pCRenderObj.Peek()); } // Reset the current lod to be the lowest possible LOD... if ((m_pCScene->Are_LODs_Switching ()) && (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_HLOD)) { - ((HLodClass *)m_pCRenderObj)->Set_LOD_Level (0); + ((HLodClass *)m_pCRenderObj.Peek())->Set_LOD_Level (0); } CGraphicView *pCGraphicView = GetGraphicView (); @@ -820,7 +770,7 @@ CW3DViewDoc::StepAnimation (int iFrameInc) m_pCRenderObj->Set_Animation (m_pCAnimCombo); } else { - m_pCRenderObj->Set_Animation (m_pCAnimation, m_CurrentFrame); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), m_CurrentFrame); } Update_Camera (); @@ -856,9 +806,8 @@ CW3DViewDoc::PlayAnimation // Get an instance of the animation object SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); - m_pCAnimation = WW3DAssetManager::Get_Instance()->Get_HAnim (pszAnimationName); - ASSERT (m_pCAnimation); + m_pCAnimation.Assign_No_Add_Ref (WW3DAssetManager::Get_Instance()->Get_HAnim (pszAnimationName)); + ASSERT (m_pCAnimation != nullptr); // Reset the frame counter m_CurrentFrame = 0; @@ -867,7 +816,7 @@ CW3DViewDoc::PlayAnimation if (m_pCRenderObj) { // Update the animation frame - m_pCRenderObj->Set_Animation (m_pCAnimation, 0); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), 0); CGraphicView *pCGraphicView = GetGraphicView (); if (pCGraphicView) @@ -944,10 +893,9 @@ CW3DViewDoc::PlayAnimation // Get an instance of the animation object SAFE_DELETE (m_pCAnimCombo); - REF_PTR_RELEASE (m_pCAnimation); m_pCAnimCombo = pCAnimCombo; - m_pCAnimation = m_pCAnimCombo->Get_Motion(0); // ref added by get_motion - ASSERT (m_pCAnimation); + m_pCAnimation.Assign_No_Add_Ref (m_pCAnimCombo->Get_Motion(0)); // ref added by get_motion + ASSERT (m_pCAnimation != nullptr); // It will be assumed that every animation in the m_pCAnimCombo // has the same number of frames and has the same framerate as @@ -1030,7 +978,7 @@ CW3DViewDoc::Update_Camera () if (m_bAnimateCamera && m_pCRenderObj != nullptr) { Matrix3D transform (1); - if (Get_Camera_Transform (m_pCRenderObj, transform)) { + if (Get_Camera_Transform (m_pCRenderObj.Peek(), transform)) { // Convert the bone's transform into a camera transform //Matrix3D transform = m_pCRenderObj->Get_Bone_Transform (index); @@ -1092,9 +1040,9 @@ CW3DViewDoc::UpdateFrame (float relativeTimeSlice) m_pCRenderObj->Set_Animation (m_pCAnimCombo); } else if (m_bAnimBlend) { - m_pCRenderObj->Set_Animation (m_pCAnimation, m_CurrentFrame); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), m_CurrentFrame); } else { - m_pCRenderObj->Set_Animation (m_pCAnimation, (int)m_CurrentFrame); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), (int)m_CurrentFrame); } Update_Camera (); @@ -1256,8 +1204,7 @@ CW3DViewDoc::SetBackgroundBMP (LPCTSTR pszBackgroundBMP) // Remove the background BMP from the scene // and release its pointer m_pCBackgroundBMP->Remove (); - m_pCBackgroundBMP->Release_Ref (); - m_pCBackgroundBMP = nullptr; + m_pCBackgroundBMP.Clear (); } // Is this a new background BMP? @@ -1265,14 +1212,14 @@ CW3DViewDoc::SetBackgroundBMP (LPCTSTR pszBackgroundBMP) (m_stringBackgroundBMP.CompareNoCase (pszBackgroundBMP) != 0)) { // Create a new instance of the BMP object to use - m_pCBackgroundBMP = new Bitmap2DObjClass (pszBackgroundBMP, 0.5F, 0.5F, TRUE, FALSE); + m_pCBackgroundBMP.Assign_No_Add_Ref (new Bitmap2DObjClass (pszBackgroundBMP, 0.5F, 0.5F, TRUE, FALSE)); // Were we successful in creating the bitmap object? ASSERT (m_pCBackgroundBMP); if (m_pCBackgroundBMP) { // Add the object to the scene - m_pC2DScene->Add_Render_Object (m_pCBackgroundBMP); + m_pC2DScene->Add_Render_Object (m_pCBackgroundBMP.Peek()); } } @@ -1796,14 +1743,13 @@ CW3DViewDoc::SetBackgroundObject (LPCTSTR pszBackgroundObjectName) m_pCBackgroundObject->Remove (); // Free the object - m_pCBackgroundObject->Release_Ref (); - m_pCBackgroundObject = nullptr; + m_pCBackgroundObject.Clear (); } if (pszBackgroundObjectName) { // Create a new instance of the render object to use as the background - m_pCBackgroundObject = WW3DAssetManager::Get_Instance()->Create_Render_Obj (pszBackgroundObjectName); + m_pCBackgroundObject.Assign_No_Add_Ref (WW3DAssetManager::Get_Instance()->Create_Render_Obj (pszBackgroundObjectName)); ASSERT (m_pCBackgroundObject); if (m_pCBackgroundObject) @@ -1827,7 +1773,7 @@ CW3DViewDoc::SetBackgroundObject (LPCTSTR pszBackgroundObjectName) m_pCBackObjectCamera->Set_Clip_Planes (1, cameraDepth); // Add the background object to the scene - m_pCBackObjectScene->Add_Render_Object (m_pCBackgroundObject); + m_pCBackObjectScene->Add_Render_Object (m_pCBackgroundObject.Peek()); } } @@ -1847,7 +1793,7 @@ CW3DViewDoc::Remove_Object_From_Scene (RenderObjClass *prender_obj) { // If the render object is null, then remove the current render object if (prender_obj == nullptr) { - prender_obj = m_pCRenderObj; + prender_obj = m_pCRenderObj.Peek(); } // Recursively remove objects from the scene (to make sure we get all particle buffers) @@ -2403,7 +2349,7 @@ CW3DViewDoc::Make_Movie () m_pCRenderObj->Set_Animation (m_pCAnimCombo); } else - m_pCRenderObj->Set_Animation (m_pCAnimation, (int)0); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), (int)0); graphic_view->RepaintView (FALSE); // Begin our movie @@ -2425,7 +2371,7 @@ CW3DViewDoc::Make_Movie () m_pCRenderObj->Set_Animation (m_pCAnimCombo); } else - m_pCRenderObj->Set_Animation (m_pCAnimation, frame); + m_pCRenderObj->Set_Animation (m_pCAnimation.Peek(), frame); // Should we be updating the camera? if (m_bAnimateCamera) { @@ -2483,7 +2429,7 @@ CW3DViewDoc::Build_Emitter_List // If the render object is null, then start from the current render object // if (render_obj == nullptr) { - render_obj = m_pCRenderObj; + render_obj = m_pCRenderObj.Peek(); } // @@ -2558,7 +2504,7 @@ void CW3DViewDoc::Create_Cursor () { if (m_pCursor == nullptr) { - m_pCursor = new ScreenCursorClass; + m_pCursor.Assign_No_Add_Ref (new ScreenCursorClass); m_pCursor->Set_Window (GetGraphicView ()->m_hWnd); m_pCursor->Set_Texture (::Load_RC_Texture ("cursor.tga")); } @@ -2579,7 +2525,7 @@ CW3DViewDoc::Count_Particles (RenderObjClass *render_obj) // If the render object is null, then start from the current render object // if (render_obj == nullptr) { - render_obj = m_pCRenderObj; + render_obj = m_pCRenderObj.Peek(); } // @@ -2638,7 +2584,7 @@ CW3DViewDoc::Switch_LOD (int increment, RenderObjClass *render_obj) // If the render object is null, then start from the current render object // if (render_obj == nullptr) { - render_obj = m_pCRenderObj; + render_obj = m_pCRenderObj.Peek(); } // @@ -2676,7 +2622,7 @@ CW3DViewDoc::Toggle_Alternate_Materials(RenderObjClass * render_obj) // If the render object is null, start from the current render object // if (render_obj == nullptr) { - render_obj = m_pCRenderObj; + render_obj = m_pCRenderObj.Peek(); } if (render_obj != nullptr) { diff --git a/Core/Tools/W3DView/W3DViewDoc.h b/Core/Tools/W3DView/W3DViewDoc.h index b92076e1a05..768af4f6480 100644 --- a/Core/Tools/W3DView/W3DViewDoc.h +++ b/Core/Tools/W3DView/W3DViewDoc.h @@ -109,15 +109,15 @@ class CW3DViewDoc : public CDocument // // Accessors // - CameraClass * Get2DCamera () const { return m_pC2DCamera; } - CameraClass * GetBackObjectCamera () const { return m_pCBackObjectCamera; } - SceneClass * Get2DScene () const { return m_pC2DScene; } - SceneClass * GetCursorScene () const { return m_pCursorScene; } - ViewerSceneClass * GetScene () const { return m_pCScene; } - SceneClass * GetBackObjectScene () const { return m_pCBackObjectScene; } - LightClass * GetSceneLight () const { return m_pCSceneLight; } - RenderObjClass * GetDisplayedObject () const { return m_pCRenderObj; } - HAnimClass * GetCurrentAnimation () const { return m_pCAnimation; } + CameraClass * Get2DCamera () const { return m_pC2DCamera.Peek(); } + CameraClass * GetBackObjectCamera () const { return m_pCBackObjectCamera.Peek(); } + SceneClass * Get2DScene () const { return m_pC2DScene.Peek(); } + SceneClass * GetCursorScene () const { return m_pCursorScene.Peek(); } + ViewerSceneClass * GetScene () const { return m_pCScene.Peek(); } + SceneClass * GetBackObjectScene () const { return m_pCBackObjectScene.Peek(); } + LightClass * GetSceneLight () const { return m_pCSceneLight.Peek(); } + RenderObjClass * GetDisplayedObject () const { return m_pCRenderObj.Peek(); } + HAnimClass * GetCurrentAnimation () const { return m_pCAnimation.Peek(); } const HTreeClass * Get_Current_HTree () const; // @@ -289,20 +289,20 @@ class CW3DViewDoc : public CDocument ////////////////////////////////////////////////////////////////// // Private member data ////////////////////////////////////////////////////////////////// - ViewerSceneClass * m_pCScene; - SceneClass * m_pC2DScene; - SceneClass * m_pCursorScene; - SceneClass * m_pCBackObjectScene; + RefCountPtr m_pCScene; + RefCountPtr m_pC2DScene; + RefCountPtr m_pCursorScene; + RefCountPtr m_pCBackObjectScene; DazzleLayerClass * m_pDazzleLayer; - RenderObjClass * m_pCRenderObj; - RenderObjClass * m_pCBackgroundObject; - HAnimClass * m_pCAnimation; + RefCountPtr m_pCRenderObj; + RefCountPtr m_pCBackgroundObject; + RefCountPtr m_pCAnimation; HAnimComboClass * m_pCAnimCombo; - LightClass * m_pCSceneLight; - Bitmap2DObjClass * m_pCBackgroundBMP; - CameraClass * m_pC2DCamera; - CameraClass * m_pCBackObjectCamera; - ScreenCursorClass * m_pCursor; + RefCountPtr m_pCSceneLight; + RefCountPtr m_pCBackgroundBMP; + RefCountPtr m_pC2DCamera; + RefCountPtr m_pCBackObjectCamera; + RefCountPtr m_pCursor; Vector3 m_backgroundColor; CString m_stringBackgroundBMP; CString m_stringBackgroundObject; diff --git a/Generals/Code/GameEngine/Include/Common/ThingTemplate.h b/Generals/Code/GameEngine/Include/Common/ThingTemplate.h index 5a696c3ae96..a2af125c3f4 100644 --- a/Generals/Code/GameEngine/Include/Common/ThingTemplate.h +++ b/Generals/Code/GameEngine/Include/Common/ThingTemplate.h @@ -144,27 +144,18 @@ enum ThingTemplateAudioType CPP_11(: Int) class AudioArray { public: - DynamicAudioEventRTS* m_audio[TTAUDIO_COUNT]; + RefCountPtr m_audio[TTAUDIO_COUNT]; - AudioArray() - { - for (Int i = 0; i < TTAUDIO_COUNT; ++i) - m_audio[i] = nullptr; - } + AudioArray() {} - ~AudioArray() - { - for (Int i = 0; i < TTAUDIO_COUNT; ++i) - if (m_audio[i]) - deleteInstance(m_audio[i]); - } + ~AudioArray() {} AudioArray(const AudioArray& that) { for (Int i = 0; i < TTAUDIO_COUNT; ++i) { if (that.m_audio[i]) - m_audio[i] = newInstance(DynamicAudioEventRTS)(*that.m_audio[i]); + m_audio[i].Assign_No_Add_Ref(newInstance(DynamicAudioEventRTS)(*that.m_audio[i])); else m_audio[i] = nullptr; } @@ -181,7 +172,7 @@ class AudioArray if (m_audio[i]) *m_audio[i] = *that.m_audio[i]; else - m_audio[i] = newInstance(DynamicAudioEventRTS)(*that.m_audio[i]); + m_audio[i].Assign_No_Add_Ref(newInstance(DynamicAudioEventRTS)(*that.m_audio[i])); } else { @@ -621,7 +612,7 @@ class ThingTemplate : public Overridable Real getBuildTime() const { return m_buildTime; } const PerUnitSoundMap* getAllPerUnitSounds() const { return &m_perUnitSounds; } void validateAudio(); - const AudioEventRTS* getAudio(ThingTemplateAudioType t) const { return m_audioarray.m_audio[t] ? &m_audioarray.m_audio[t]->m_event : &s_audioEventNoSound; } + const AudioEventRTS* getAudio(ThingTemplateAudioType t) const { return m_audioarray.m_audio[t] ? m_audioarray.m_audio[t].Peek() : &s_audioEventNoSound; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** Table for parsing the object fields */ diff --git a/Generals/Code/GameEngine/Include/GameClient/Drawable.h b/Generals/Code/GameEngine/Include/GameClient/Drawable.h index ad10910bc73..bbe206ff429 100644 --- a/Generals/Code/GameEngine/Include/GameClient/Drawable.h +++ b/Generals/Code/GameEngine/Include/GameClient/Drawable.h @@ -53,6 +53,7 @@ class Shadow; class ModuleInfo; class Anim2DTemplate; class Image; +class DynamicAudioEventInfo; enum BodyDamageType CPP_11(: Int); // this is a very worthwhile performance win. left conditionally defined for now, just @@ -148,6 +149,8 @@ class DrawableLocoInfo : public MemoryPoolObject Real m_overlapZVel; ///< fake Z velocity Real m_overlapZ; ///< current height (additional) Real m_wobble; ///< for wobbling + Real m_yawModulator; ///< for the swimmy soft hover of a helicopter + Real m_pitchModulator; ///< for the swimmy soft hover of a helicopter TWheelInfo m_wheelInfo; ///< Wheel offset & angle info for a wheeled type locomotor. DrawableLocoInfo(); @@ -240,6 +243,8 @@ enum TintStatus CPP_11(: Int) TINT_STATUS_DISABLED = 0x00000001,///< drawable tint color is deathly dark grey TINT_STATUS_IRRADIATED = 0x00000002,///< drawable tint color is sickly green TINT_STATUS_POISONED = 0x00000004,///< drawable tint color is open-sore red + TINT_STATUS_GAINING_SUBDUAL_DAMAGE = 0x00000008,///< When gaining subdual damage, we tint SUBDUAL_DAMAGE_COLOR + TINT_STATUS_FRENZY = 0x00000010,///< When frenzied, we tint FRENZY_COLOR }; @@ -297,6 +302,7 @@ class Drawable : public Thing, Drawable( const ThingTemplate *thing, DrawableStatusBits statusBits = DRAWABLE_STATUS_DEFAULT ); void onDestroy(); ///< run from GameClient::destroyDrawable + void onLevelStart(); ///< run from GameLogic::startNewGame Drawable *getNextDrawable() const { return m_nextDrawable; } ///< return the next drawable in the global list Drawable *getPrevDrawable() const { return m_prevDrawable; } ///< return the prev drawable in the global list @@ -360,6 +366,7 @@ class Drawable : public Thing, ClientUpdateModule* findClientUpdateModule( NameKeyType key ); // never returns null + DrawModule** getDrawModulesNonDirty(); DrawModule** getDrawModules(); DrawModule const** getDrawModules() const; @@ -404,15 +411,16 @@ class Drawable : public Thing, const Matrix3D *getTransformMatrix() const; ///< return the world transform - void draw( View *view ); ///< render the drawable to the given view + void draw(); ///< render the drawable to the given view void updateDrawable(); ///< update the drawable void drawIconUI(); ///< draw "icon"(s) needed on drawable (health bars, veterency, etc) - void startAmbientSound(); + void startAmbientSound( Bool onlyIfPermanent = false ); void stopAmbientSound(); void enableAmbientSound( Bool enable ); void setTimeOfDay( TimeOfDay tod ); + Bool getAmbientSoundEnabledFromScript() const { return m_ambientSoundEnabledFromScript; } void prependToList(Drawable **pListHead); void removeFromList(Drawable **pListHead); @@ -455,6 +463,8 @@ class Drawable : public Thing, const TWheelInfo *getWheelInfo() const { return m_locoInfo ? &m_locoInfo->m_wheelInfo : nullptr; } + const DrawableLocoInfo *getLocoInfo() const { return m_locoInfo; } + // this method must ONLY be called from the client, NEVER From the logic, not even indirectly. Bool clientOnly_getFirstRenderObjInfo(Coord3D* pos, Real* boundingSphereRadius, Matrix3D* transform); @@ -492,6 +502,10 @@ class Drawable : public Thing, "in between", it is included in the completion time. */ void setAnimationCompletionTime(UnsignedInt numFrames); + + //Kris: Manually set a drawable's current animation to specific frame. + virtual void setAnimationFrame( int frame ); + void updateSubObjects(); void showSubObject( const AsciiString& name, Bool show ); @@ -554,11 +568,26 @@ class Drawable : public Thing, void killIcon(DrawableIconType t) { if (m_iconInfo) m_iconInfo->killIcon(t); } Bool hasIconInfo() const { return m_iconInfo != nullptr; } - const AudioEventRTS * getAmbientSound() const { return m_ambientSound == nullptr ? nullptr : &m_ambientSound->m_event; } Bool getReceivesDynamicLights() { return m_receivesDynamicLights; }; void setReceivesDynamicLights( Bool set ) { m_receivesDynamicLights = set; }; + //--------------------------------------------------------------------------------- + // Stuff for overriding ambient sound + const AudioEventInfo * getBaseSoundAmbientInfo() const; //< Possible starting point if only some parameters are customized + void enableAmbientSoundFromScript( Bool enable ); + const AudioEventRTS * getAmbientSound() const { return m_ambientSound == nullptr ? nullptr : m_ambientSound.Peek(); } + void setCustomSoundAmbientOff(); //< Kill the ambient sound + void setCustomSoundAmbientInfo( DynamicAudioEventInfo * customAmbientInfo ); //< Set ambient sound. + void clearCustomSoundAmbient() { clearCustomSoundAmbient( true ); } //< Return to using defaults + Bool getAmbientSoundEnabled() const { return m_ambientSoundEnabled; } + void mangleCustomAudioName( DynamicAudioEventInfo * audioToMangle ) const; + + + Real friend_getStealthOpacity() { return m_stealthOpacity; } + Real friend_getExplicitOpacity() { return m_explicitOpacity; } + Real friend_getEffectiveStealthOpacity() { return m_effectiveStealthOpacity; } + protected: // snapshot methods @@ -567,7 +596,7 @@ class Drawable : public Thing, virtual void loadPostProcess() override; void xferDrawableModules( Xfer *xfer ); - void startAmbientSound(BodyDamageType dt, TimeOfDay tod); + void startAmbientSound( BodyDamageType dt, TimeOfDay tod, Bool onlyIfPermanent = false ); virtual Drawable *asDrawableMeth() override { return this; } virtual const Drawable *asDrawableMeth() const override { return this; } @@ -601,9 +630,12 @@ class Drawable : public Thing, void calcPhysicsXformHoverOrWings(const Locomotor *locomotor, PhysicsXformInfo& info); void calcPhysicsXformTreads(const Locomotor *locomotor, PhysicsXformInfo& info); void calcPhysicsXformWheels(const Locomotor *locomotor, PhysicsXformInfo& info); + void calcPhysicsXformMotorcycle( const Locomotor *locomotor, PhysicsXformInfo& info ); const AudioEventRTS& getAmbientSoundByDamage(BodyDamageType dt); + void clearCustomSoundAmbient( bool restartSound ); //< Return to using defaults + #ifdef RTS_DEBUG void validatePos() const; #endif @@ -615,6 +647,8 @@ class Drawable : public Thing, private: + const Locomotor* getLocomotor() const; + // note, these are lazily allocated! TintEnvelope* m_selectionFlashEnvelope; ///< used for selection flash, works WITH m_colorTintEnvelope TintEnvelope* m_colorTintEnvelope; ///< house color flashing, etc... works WITH m_selectionFlashEnvelope @@ -640,6 +674,8 @@ class Drawable : public Thing, Drawable *m_nextDrawable; Drawable *m_prevDrawable; ///< list links + DynamicAudioEventInfo *m_customSoundAmbientInfo; ///< If not nullptr, info about the ambient sound to attach to this object + DrawableStatusBits m_status; ///< status bits (see DrawableStatus enum) UnsignedInt m_tintStatus; ///< tint color status bits (see TintStatus enum) UnsignedInt m_prevTintStatus;///< for edge testing with m_tintStatus @@ -658,8 +694,9 @@ class Drawable : public Thing, DrawableLocoInfo* m_locoInfo; // lazily allocated - DynamicAudioEventRTS* m_ambientSound; ///< sound module for ambient sound (lazily allocated) - Bool m_ambientSoundEnabled; + PhysicsXformInfo* m_physicsXform; + + RefCountPtr m_ambientSound; ///< sound module for ambient sound (lazily allocated) Module** m_modules[NUM_DRAWABLE_MODULE_TYPES]; @@ -690,6 +727,8 @@ class Drawable : public Thing, Bool m_hiddenByStealth; ///< drawable is hidden due to stealth Bool m_instanceIsIdentity; ///< If true, instance matrix can be skipped Bool m_drawableFullyObscuredByShroud; ///