diff --git a/Core/GameEngine/Include/Common/AudioEventInfo.h b/Core/GameEngine/Include/Common/AudioEventInfo.h index 144cddefda..397cfe9e5f 100644 --- a/Core/GameEngine/Include/Common/AudioEventInfo.h +++ b/Core/GameEngine/Include/Common/AudioEventInfo.h @@ -80,6 +80,7 @@ enum AudioControl CPP_11(: Int) AC_ALL = 0x0004, AC_POSTDELAY = 0x0008, AC_INTERRUPT = 0x0010, + AC_STOPEARLY = 0x0020, }; class DynamicAudioEventInfo; diff --git a/Core/GameEngine/Include/Common/GameAudio.h b/Core/GameEngine/Include/Common/GameAudio.h index 3b0bc483b0..8aca719bbc 100644 --- a/Core/GameEngine/Include/Common/GameAudio.h +++ b/Core/GameEngine/Include/Common/GameAudio.h @@ -194,7 +194,7 @@ class AudioManager : public SubsystemInterface virtual void *getDevice( void ) = 0; // Debice Dependent notification functions - virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ) = 0; + virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags, bool isEarlyStop = false) = 0; // Device Dependent enumerate providers functions. It is okay for there to be only 1 provider (Miles provides a maximum of 64. virtual UnsignedInt getProviderCount( void ) const = 0; @@ -399,7 +399,7 @@ class AudioManagerDummy : public AudioManager virtual void openDevice() {} virtual void closeDevice() {} virtual void* getDevice() { return NULL; } - virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags) {} + virtual void notifyOfAudioCompletion(UnsignedInt audioCompleted, UnsignedInt flags, bool isEarlyStop=false) {} virtual UnsignedInt getProviderCount(void) const { return 0; }; virtual AsciiString getProviderName(UnsignedInt providerNum) const { return ""; } virtual UnsignedInt getProviderIndex(AsciiString providerName) const { return 0; } diff --git a/Core/GameEngine/Source/Common/INI/INIAudioEventInfo.cpp b/Core/GameEngine/Source/Common/INI/INIAudioEventInfo.cpp index 0ea67eee6b..e87d877d56 100644 --- a/Core/GameEngine/Source/Common/INI/INIAudioEventInfo.cpp +++ b/Core/GameEngine/Source/Common/INI/INIAudioEventInfo.cpp @@ -210,6 +210,7 @@ const char *theAudioControlNames[] = "ALL", "POSTDELAY", "INTERRUPT", + "STOPEARLY", NULL }; diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index 73bcc580db..291c099566 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -172,7 +172,7 @@ class MilesAudioManager : public AudioManager ///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE virtual Bool isCurrentlyPlaying( AudioHandle handle ); - virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ); + virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags, bool isEarlyStop=false ); virtual PlayingAudio *findPlayingAudioFrom( UnsignedInt audioCompleted, UnsignedInt flags ); virtual UnsignedInt getProviderCount( void ) const; @@ -276,6 +276,8 @@ class MilesAudioManager : public AudioManager void initFilters( HSAMPLE sample, const AudioEventRTS *eventInfo ); void initFilters3D( H3DSAMPLE sample, const AudioEventRTS *eventInfo, const Coord3D *pos ); + // void handleLoopStopEarly(PlayingAudio* audio); + protected: ProviderInfo m_provider3D[MAXPROVIDERS]; UnsignedInt m_providerCount; diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 73965d64d0..012485ba4a 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -894,6 +894,25 @@ void MilesAudioManager::playAudioEvent( AudioEventRTS *event ) } } +//------------------------------------------- +//void MilesAudioManager::handleLoopStopEarly(PlayingAudio* audio) { +// if (!(audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY)) { +// // We shouldn't be here. +// DEBUG_LOG((">>> handleLoopStopEarly - invalid audio: %s\n", audio->m_audioEventRTS->getEventName().str())); +// return; +// } +// +// // We assume we have a looping sound and jump right to Decay portion +// // -> create new event, and set old one as kill handle +// +// //That's probably a bad idea actually, since it changes the handle. :( +// +// if (audio->m_type == PAT_3DSample) { +// +// // event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle()); +// } +//} + //------------------------------------------------------------------------------------------------- void MilesAudioManager::stopAudioEvent( AudioHandle handle ) { @@ -936,6 +955,7 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) if (audio->m_audioEventRTS->getPlayingHandle() == handle) { // found it audio->m_requestStop = true; + notifyOfAudioCompletion((UnsignedInt)(audio->m_stream), PAT_Stream); break; } @@ -948,7 +968,13 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) } if (audio->m_audioEventRTS->getPlayingHandle() == handle) { + audio->m_requestStop = true; + if (audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { + // DEBUG_LOG((">>> stopAudioEvent (sounds): %s\n", audio->m_audioEventRTS->getEventName().str())); + notifyOfAudioCompletion((UnsignedInt)(audio->m_sample), PAT_Sample, true); + } + break; } } @@ -963,7 +989,15 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) #ifdef INTENSIVE_AUDIO_DEBUG DEBUG_LOG((" (%s)", audio->m_audioEventRTS->getEventName())); #endif + audio->m_requestStop = true; + + if (audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { + // DEBUG_LOG((">>> stopAudioEvent (3DSounds): %s\n", audio->m_audioEventRTS->getEventName().str())); + + notifyOfAudioCompletion((UnsignedInt)(audio->m_3DSample), PAT_3DSample, true); + } + break; } } @@ -1524,7 +1558,7 @@ Bool MilesAudioManager::isCurrentlyPlaying( AudioHandle handle ) } //------------------------------------------------------------------------------------------------- -void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ) +void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags, bool isEarlyStop/*= false*/) { PlayingAudio *playing = findPlayingAudioFrom(audioCompleted, flags); if (!playing) { @@ -1537,21 +1571,55 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns } 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)) { + // Early stop + if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY && playing->m_requestStop) { + + if (!isEarlyStop) { + // We came here from the audio being stopped by other means. + // To avoid doing things twice, we just return here. I hope this doesn't break things. + //DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 1: %s (%s) - nextPP = %d - isEarlyStop = FALSE\n", + // playing->m_audioEventRTS->getEventName().str(), + // playing->m_audioEventRTS->getFilename().str(), + // playing->m_audioEventRTS->getNextPlayPortion())); return; } + + //DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 1: %s (%s) - nextPP = %d\n", + // playing->m_audioEventRTS->getEventName().str(), + // playing->m_audioEventRTS->getFilename().str(), + // playing->m_audioEventRTS->getNextPlayPortion())); + + // How to advance? + // - Attack -> Decay + // - Sound -> Decay + // - Decay -> this shouldn't really happen. + // We jump from Attack to Sound, so we then advance to Decay + if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Attack) { + playing->m_audioEventRTS->setNextPlayPortion(PP_Sound); + } + } + // Normal loop behavior + else { + + 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.