From 21dd84870b793806b5870e0e0c6487236a13076e Mon Sep 17 00:00:00 2001 From: Andi Date: Fri, 8 Aug 2025 10:34:54 +0200 Subject: [PATCH 1/3] first attempt (WIP) - kinda bad --- .../Include/Common/AudioEventInfo.h | 1 + .../Source/Common/INI/INIAudioEventInfo.cpp | 1 + .../MilesAudioDevice/MilesAudioManager.cpp | 87 +++++++++++++++++-- 3 files changed, 81 insertions(+), 8 deletions(-) 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/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/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 73965d64d0..d6b6d87f3d 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -936,6 +936,11 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) if (audio->m_audioEventRTS->getPlayingHandle() == handle) { // found it audio->m_requestStop = true; + + if (audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { + DEBUG_LOG((">>> stopAudioEvent (stream): %s\n", audio->m_audioEventRTS->getEventName().str())); + } + notifyOfAudioCompletion((UnsignedInt)(audio->m_stream), PAT_Stream); break; } @@ -948,6 +953,11 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) } if (audio->m_audioEventRTS->getPlayingHandle() == handle) { + + if (audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { + DEBUG_LOG((">>> stopAudioEvent (sounds): %s\n", audio->m_audioEventRTS->getEventName().str())); + } + audio->m_requestStop = true; break; } @@ -963,7 +973,17 @@ 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())); + + //We should move to next loop instead? + //notifyOfAudioCompletion((UnsignedInt)(audio->m_3DSample), PAT_3DSample); + } + break; } } @@ -1537,21 +1557,61 @@ 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); + + // Early stop + if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY && playing->m_requestStop) { + + //Bool isEarlyStop = + + DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 1: %s (%s) - nextPP = %d\n", + playing->m_audioEventRTS->getEventName().str(), + playing->m_audioEventRTS->getFilename().str(), + playing->m_audioEventRTS->getNextPlayPortion())); + + //playing->m_requestStop = false; + + // 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); + } + + // Do we need to artificially stop the current sound? + } - if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Sound) { - // First, decrease the loop count. - playing->m_audioEventRTS->decreaseLoopCount(); + // Normal loop behavior + else { - // Now, try to start the next loop - if (startNextLoop(playing)) { - return; + 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)) { + // DEBUG_LOG((">>> notifyOfAudioCompletion: %s - startNextLoop -> DONE?\n", playing->m_audioEventRTS->getEventName().str())); + return; + } } } } playing->m_audioEventRTS->advanceNextPlayPortion(); + + if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { + + DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 2: %s (%s) - nextPP = %d\n", + playing->m_audioEventRTS->getEventName().str(), + playing->m_audioEventRTS->getFilename().str(), + playing->m_audioEventRTS->getNextPlayPortion())); + } + 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. @@ -1563,12 +1623,23 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns return; } } else if (playing->m_type == PAT_3DSample) { + DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 3a: %s (%s) - nextPP = %d\n", + playing->m_audioEventRTS->getEventName().str(), + playing->m_audioEventRTS->getFilename().str(), + playing->m_audioEventRTS->getNextPlayPortion())); + 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) { + + DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 3b - play next: %s (%s) - nextPP = %d\n", + playing->m_audioEventRTS->getEventName().str(), + playing->m_audioEventRTS->getFilename().str(), + playing->m_audioEventRTS->getNextPlayPortion())); + return; } } From f7112e26b0261287af5b9b5bfea6e9019da636f3 Mon Sep 17 00:00:00 2001 From: Andi Date: Fri, 8 Aug 2025 11:19:29 +0200 Subject: [PATCH 2/3] This seems to work now --- Core/GameEngine/Include/Common/GameAudio.h | 4 +-- .../MilesAudioDevice/MilesAudioManager.h | 4 ++- .../MilesAudioDevice/MilesAudioManager.cpp | 33 +++++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) 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/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 d6b6d87f3d..133c340547 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 ) { @@ -981,7 +1000,7 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) DEBUG_LOG((">>> stopAudioEvent (3DSounds): %s\n", audio->m_audioEventRTS->getEventName().str())); //We should move to next loop instead? - //notifyOfAudioCompletion((UnsignedInt)(audio->m_3DSample), PAT_3DSample); + notifyOfAudioCompletion((UnsignedInt)(audio->m_3DSample), PAT_3DSample, true); } break; @@ -1544,7 +1563,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) { @@ -1561,7 +1580,15 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns // Early stop if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY && playing->m_requestStop) { - //Bool isEarlyStop = + 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(), From b35414de8f1e3c89dde9c0c3bce845ff07da7d84 Mon Sep 17 00:00:00 2001 From: Andi Date: Fri, 8 Aug 2025 13:42:09 +0200 Subject: [PATCH 3/3] cleanup --- .../MilesAudioDevice/MilesAudioManager.cpp | 54 +++++-------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 133c340547..012485ba4a 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -956,10 +956,6 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) // found it audio->m_requestStop = true; - if (audio->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { - DEBUG_LOG((">>> stopAudioEvent (stream): %s\n", audio->m_audioEventRTS->getEventName().str())); - } - notifyOfAudioCompletion((UnsignedInt)(audio->m_stream), PAT_Stream); break; } @@ -973,11 +969,12 @@ 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())); + // DEBUG_LOG((">>> stopAudioEvent (sounds): %s\n", audio->m_audioEventRTS->getEventName().str())); + notifyOfAudioCompletion((UnsignedInt)(audio->m_sample), PAT_Sample, true); } - audio->m_requestStop = true; break; } } @@ -993,13 +990,11 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) 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())); + // DEBUG_LOG((">>> stopAudioEvent (3DSounds): %s\n", audio->m_audioEventRTS->getEventName().str())); - //We should move to next loop instead? notifyOfAudioCompletion((UnsignedInt)(audio->m_3DSample), PAT_3DSample, true); } @@ -1583,19 +1578,17 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns 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())); + //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())); - - //playing->m_requestStop = false; + //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 @@ -1605,9 +1598,6 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Attack) { playing->m_audioEventRTS->setNextPlayPortion(PP_Sound); } - - // Do we need to artificially stop the current sound? - } // Normal loop behavior else { @@ -1622,7 +1612,6 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns // Now, try to start the next loop if (startNextLoop(playing)) { - // DEBUG_LOG((">>> notifyOfAudioCompletion: %s - startNextLoop -> DONE?\n", playing->m_audioEventRTS->getEventName().str())); return; } } @@ -1631,14 +1620,6 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns playing->m_audioEventRTS->advanceNextPlayPortion(); - if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_STOPEARLY) { - - DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 2: %s (%s) - nextPP = %d\n", - playing->m_audioEventRTS->getEventName().str(), - playing->m_audioEventRTS->getFilename().str(), - playing->m_audioEventRTS->getNextPlayPortion())); - } - 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. @@ -1650,23 +1631,12 @@ void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, Uns return; } } else if (playing->m_type == PAT_3DSample) { - DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 3a: %s (%s) - nextPP = %d\n", - playing->m_audioEventRTS->getEventName().str(), - playing->m_audioEventRTS->getFilename().str(), - playing->m_audioEventRTS->getNextPlayPortion())); - 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) { - - DEBUG_LOG((">>> notifyOfAudioCompletion EARLYSTOP 3b - play next: %s (%s) - nextPP = %d\n", - playing->m_audioEventRTS->getEventName().str(), - playing->m_audioEventRTS->getFilename().str(), - playing->m_audioEventRTS->getNextPlayPortion())); - return; } }