From 86ae2ae3953f72a8d96c7359b7bf9fd2614b2cad Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 25 Aug 2017 16:08:49 -0400 Subject: [PATCH] Improved shuffle (#1412) --- AUTHORS.md | 1 + apps/openmw/mwsound/soundmanagerimp.cpp | 25 +++++++++++++++++-------- apps/openmw/mwsound/soundmanagerimp.hpp | 2 ++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index c48647f4e..bb773c4ef 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -60,6 +60,7 @@ Programmers Gašper Sedej gugus/gus Hallfaer Tuilinn + Haoda Wang (h313) hristoast Internecine Jacob Essex (Yacoby) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index c6f663059..811797369 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -271,7 +272,6 @@ namespace MWSound return sound; } - // Gets the combined volume settings for the given sound type float SoundManager::volumeFromType(PlayType type) const { @@ -298,7 +298,6 @@ namespace MWSound return volume; } - void SoundManager::stopMusic() { if(mMusic) @@ -349,6 +348,7 @@ namespace MWSound void SoundManager::startRandomTitle() { std::vector filelist; + auto &tracklist = mMusicToPlay[mCurrentPlaylist]; if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end()) { const std::map& index = mVFS->getIndex(); @@ -367,7 +367,6 @@ namespace MWSound } mMusicFiles[mCurrentPlaylist] = filelist; - } else filelist = mMusicFiles[mCurrentPlaylist]; @@ -375,15 +374,25 @@ namespace MWSound if(filelist.empty()) return; - int i = Misc::Rng::rollDice(filelist.size()); + // Do a Fisher-Yates shuffle - // Don't play the same music track twice in a row - if (filelist[i] == mLastPlayedMusic) + // Repopulate if playlist is empty + if(tracklist.empty()) { - i = (i+1) % filelist.size(); + tracklist.resize(filelist.size()); + std::iota(tracklist.begin(), tracklist.end(), 0); } - advanceMusic(filelist[i]); + int i = Misc::Rng::rollDice(tracklist.size()); + + // Reshuffle if last played music is the same after a repopulation + if(filelist[tracklist[i]] == mLastPlayedMusic) + i = (i+1) % tracklist.size(); + + // Remove music from list after advancing music + advanceMusic(filelist[tracklist[i]]); + tracklist[i] = tracklist.back(); + tracklist.pop_back(); } bool SoundManager::isMusicPlaying() diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 5d911d4be..691e52932 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -49,6 +50,7 @@ namespace MWSound // Caches available music tracks by std::map > mMusicFiles; + std::unordered_map> mMusicToPlay; // A list with music files not yet played std::string mLastPlayedMusic; // The music file that was last played float mMasterVolume;