Skip to content

Commit

Permalink
Merge pull request #63 from TwinFan/next
Browse files Browse the repository at this point in the history
v3.3.1 Fixes: Freeze in XP12.0.8 / Sound Crackling
  • Loading branch information
TwinFan committed Nov 11, 2023
2 parents 202792c + 88ecfe1 commit 36db88d
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 18 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ else()
endif()

project(XPMP2
VERSION 3.3.0
VERSION 3.3.1
DESCRIPTION "Multiplayer library for X-Plane 11 and 12")

# Provide compile macros from the above project version definition
Expand Down
4 changes: 2 additions & 2 deletions XPMP2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@
);
XPMP2_VER_MAJOR = 3;
XPMP2_VER_MINOR = 3;
XPMP2_VER_PATCH = 0;
XPMP2_VER_PATCH = 1;
XPSDK_ROOT = lib/SDK;
};
name = Debug;
Expand Down Expand Up @@ -583,7 +583,7 @@
);
XPMP2_VER_MAJOR = 3;
XPMP2_VER_MINOR = 3;
XPMP2_VER_PATCH = 0;
XPMP2_VER_PATCH = 1;
XPSDK_ROOT = lib/SDK;
};
name = Release;
Expand Down
18 changes: 8 additions & 10 deletions src/AIMultiplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,26 +749,24 @@ int AIMultiControlPlaneCount(
//

/// @brief Resets all actual values of the AI/multiplayer dataRefs of one plane to something initial
/// @note There as pending bug, filed as XPD-13332, which affects this function with XP12 on Mac.
/// @note There as pending bug, filed as XPD-13332, which affects this function with XP12.
/// X-Plane 12 can freeze since b5 when clearing Multiplayer positions to zero.
/// @see https://forums.x-plane.org/index.php?/forums/topic/276319-xp12-on-mac-since-b5-freeze-upon-tcas-activation/
/// @see also https://forums.x-plane.org/index.php?/forums/topic/296584-livetraffic-freezes-xp-1208beta1-on-taking-over-tcas/
/// reporting the same issue for Linux, so we switch initializing off completely.
void AIMultiClearAIDataRefs (multiDataRefsTy& drM,
bool bDeactivateToZero)
{
// not ok dataRefs?
if (!drM) return;

#if APL
// Apple Workaround for XP12: Don't init position, otherwise may freeze
// XPD-13332 Workaround for XP12: Don't init position, otherwise may freeze
if (glob.verXPlane < 12000) {
#endif
// either a "far away" location or standard 0, which is, however, a valid location somewhere!
XPLMSetDataf(drM.X, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
XPLMSetDataf(drM.Y, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
XPLMSetDataf(drM.Z, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
#if APL
// either a "far away" location or standard 0, which is, however, a valid location somewhere!
XPLMSetDataf(drM.X, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
XPLMSetDataf(drM.Y, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
XPLMSetDataf(drM.Z, bDeactivateToZero ? 0.0f : FAR_AWAY_VAL_GL);
}
#endif

XPLMSetDataf(drM.v_x, 0.0f); // zero speed
XPLMSetDataf(drM.v_y, 0.0f);
Expand Down
37 changes: 33 additions & 4 deletions src/Sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,24 @@ std::pair<uint64_t,SoundChannel*> SoundSystem::AddChn (SoundFile* pSnd, float vo
// Return the SoundChannel object for a given id, or `nullptr` if not found
SoundChannel* SoundSystem::GetChn (uint64_t sndId)
{
// check cached value first
if (cacheSndId == sndId && pCacheChn)
return pCacheChn;
// search in map of channels
auto i = mapChn.find(sndId);
if (i != mapChn.end())
return &i->second;
if (i != mapChn.end()) {
cacheSndId = sndId; // fill cache
return pCacheChn = &i->second;
}
else
return nullptr;
}

// Remove a channel from out tracking
void SoundSystem::RemoveChn (uint64_t sndId)
{
if (cacheSndId == sndId) // clear cache
pCacheChn = nullptr;
mapChn.erase(sndId);
}

Expand Down Expand Up @@ -480,7 +488,13 @@ uint64_t SoundSystemXP::Play (const std::string& sndName, float vol, const Aircr
xplm_AudioExteriorEnvironment,
PlayCallback, (void*)sndId);
if (!pChn->pChn) throw std::runtime_error("XPLMPlayPCMOnBus return NULL");

#if INCLUDE_FMOD_SOUND + 0 >= 1
// if we have FMOD available then start in a paused state to avoid crackling
FMOD_LOG(FMOD_Channel_SetPaused(pChn->pChn, true));
#else
pChn->nPauseCountdown = 0;
#endif

// Set a few more parameters to the sound
FMOD_LOG(gpXPLMSetAudioFadeDistance(pChn->pChn, (float)ac.sndMinDist, FMOD_3D_MAX_DIST));
SetPosOrientation(sndId, ac, true);
Expand Down Expand Up @@ -525,6 +539,20 @@ void SoundSystemXP::PlayCallback (void* inRefcon,
me->RemoveChn(sndId);
}

// Unpause a sound, which got started in a paused state to avoid crackling
/// @note Only available if built with FMOD library
void SoundSystemXP::Unpause (uint64_t sndId)
{
#if INCLUDE_FMOD_SOUND + 0 >= 1
SoundChannel* pChn = GetChn(sndId);
if (!pChn || !pChn->pChn) return;

if (pChn->ShallUnpause()) {
FMOD_LOG(FMOD_Channel_SetPaused(pChn->pChn, false));
}
#endif
}


// Stop the sound
void SoundSystemXP::Stop (uint64_t sndId)
Expand Down Expand Up @@ -895,7 +923,7 @@ void Aircraft::SoundUpdate ()
}
}

// --- Update all channels' 3D position
// --- Unpause and Update all channels' 3D position

// Decide here already if this time we do expensive computations (like sound cone orientation)
bool bDoExpensiveComp = false;
Expand All @@ -909,6 +937,7 @@ void Aircraft::SoundUpdate ()
// Still valid?
const uint64_t sndId = *iter;
if (gpSndSys->IsValid(sndId)) {
gpSndSys->Unpause(sndId);
gpSndSys->SetPosOrientation(sndId, *this, bDoExpensiveComp);
iter++;
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/Sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,16 @@ class SoundChannel {
SoundFile* pSnd = nullptr; ///< the sound file the sound was created from
float vol = 1.0f; ///< volume (if not muted)
bool bMuted = false; ///< currently muted?
int nPauseCountdown = 2; ///< frame till unpause this sound (starts paused to avoid crackling)
public:
/// Default Constructor creates an invalid object
SoundChannel () {}
/// Constructor
SoundChannel (FMOD_CHANNEL* c, SoundFile* s, float v) : pChn(c), pSnd(s), vol(v) {}
/// Has valid pointers? (Doesn't say if actual objects are valid any longer)
operator bool () const { return pChn && pSnd; }
/// Need to unpause now? (returns `true` only once when countdown reaches zero)
bool ShallUnpause () { return nPauseCountdown > 0 ? (--nPauseCountdown == 0) : false; }
};

/// Base class for sound systems, practically empty
Expand All @@ -201,6 +204,9 @@ class SoundSystem {
private:
/// Next sound channel id
uint64_t uNxtId = 0;
/// Cache to avoid re-lookup of repeatedly same sound id
uint64_t cacheSndId = 0;
SoundChannel* pCacheChn = nullptr;

public:
/// Construtor
Expand All @@ -218,6 +224,8 @@ class SoundSystem {

/// Play a new sound, returns an id for that sound
virtual uint64_t Play (const std::string& sndName, float vol, const Aircraft& ac) = 0;
/// Unpause a sound, which got started in a paused state to avoid crackling
virtual void Unpause (uint64_t sndId) = 0;
/// Stop the sound
virtual void Stop (uint64_t sndId) = 0;
/// Update sound's position and orientation
Expand Down Expand Up @@ -274,6 +282,8 @@ class SoundSystemXP : public SoundSystem {

/// Play a new sound, returns an id for that sound
uint64_t Play (const std::string& sndName, float vol, const Aircraft& ac) override;
/// Unpause a sound, which got started in a paused state to avoid crackling
void Unpause (uint64_t sndId) override;
/// Stop the sound
void Stop (uint64_t sndId) override;
/// Update sound's position and orientation
Expand Down
15 changes: 14 additions & 1 deletion src/SoundFMOD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ uint64_t SoundSystemFMOD::Play (const std::string& sndName, float vol, const Air
SoundFMOD* pSndFmod = dynamic_cast<SoundFMOD*>(pSnd.get());
if (!pSndFmod) throw std::runtime_error("Sound has not been loaded for FMOD system");

FMOD_TEST(FMOD_System_PlaySound(pFmodSystem, pSndFmod->GetSnd(), pChnGrp, ac.SoundIsMuted(), &pFmodChn));
// Start playing the sound, but in a paused state to avoid crackling
FMOD_TEST(FMOD_System_PlaySound(pFmodSystem, pSndFmod->GetSnd(), pChnGrp, true, &pFmodChn));
if (!pFmodChn) throw std::runtime_error("FMOD_System_PlaySound returned NULL channel");

// We must keep track of the sounds we produce so we can clean up after us
Expand All @@ -310,6 +311,7 @@ uint64_t SoundSystemFMOD::Play (const std::string& sndName, float vol, const Air
}
SetPosOrientation(sndId, ac, true);
FMOD_LOG(FMOD_Channel_SetVolume(pFmodChn, vol));
FMOD_LOG(FMOD_Channel_SetMute(pFmodChn, ac.SoundIsMuted()));
if (bLowPass) {
FMOD_LOG(FMOD_Channel_SetLowPassGain(pFmodChn, FMOD_LOW_PASS_GAIN));
}
Expand All @@ -329,6 +331,17 @@ uint64_t SoundSystemFMOD::Play (const std::string& sndName, float vol, const Air

return 0;
}

// Unpause a sound, which got started in a paused state to avoid crackling
void SoundSystemFMOD::Unpause (uint64_t sndId)
{
SoundChannel* pChn = GetChn(sndId);
if (!pChn || !pChn->pChn) return;

if (pChn->ShallUnpause()) {
FMOD_LOG(FMOD_Channel_SetPaused(pChn->pChn, false));
}
}

// Stop the sound
void SoundSystemFMOD::Stop (uint64_t sndId)
Expand Down
2 changes: 2 additions & 0 deletions src/SoundFMOD.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class SoundSystemFMOD : public SoundSystem {

/// Play a new sound, returns an id for that sound
uint64_t Play (const std::string& sndName, float vol, const Aircraft& ac) override;
/// Unpause a sound, which got started in a paused state to avoid crackling
void Unpause (uint64_t sndId) override;
/// Stop the sound
void Stop (uint64_t sndId) override;
/// Update sound's position and orientation
Expand Down

0 comments on commit 36db88d

Please sign in to comment.