captbaritone / webamp

Winamp 2 reimplemented for the browser
https://webamp.org
MIT License
10.25k stars 695 forks source link

Make shuffle mode more clever #716

Open captbaritone opened 5 years ago

captbaritone commented 5 years ago

When the user enables shuffle mode, we should generate a shadow playlist order that has been shuffled and play from that instead. Adding new tracks should add them to the "unplayed" part of the playlist. Deleting a track should remove it from the playlist.

When the end of the playlist is reached, it should stop.

From Dr. O:

and this is why people complain about winamp proper's shuffle handling at times :wink: as we've been talking about it recently as some seem to get repeats when shuffle is on when others don't & it works off a pre-generated shuffle list (with removals taken out & additions added into the part that's remaining to be played)

GChuf commented 5 years ago

Just posting ideas from our discord conversation here so that it doesn't get lost:

From Chuf:

You make a new empty array (or overwrite previous one) when the user toggles Shuffle. This array (PlayedSongsArray) would keep in memory all the songs that were played already, ever since Shuffle was toggled. When you get to the PlayRandomSong, you create a new temporary array that gets overwritten every time: TemporaryArray = PlaylistArray - PlayedSongsArray So now you have the temporary array with all the songs that werent played yet, and you pick a random song from this array instead a random song from the playlist array as it's done now. Then, you append this randomly selected song to the PlayedSongsArray.(edited) When PlayedSongsArray length equals the playlist array length (when all the songs in the playlist were played), you delete the first half of the PlayedSongsArray. You could delete the whole array, but if you only delete only the first half for example, you make sure that the songs wouldnt be repetitive after the whole playlist has been played, if that makes sense. In other words, after the playlist has ended, the program makes sure that the next played song will not be one of the recently played songs. This way, adding songs doesn't impact the selection of the "random" song, because the temporary array is created every time before a song gets played. So if the playlist updates, the next temporary array would just remove already played songs from the new playlist array. And if a song gets removed, to ensure nothing weird happens, you should remove them from the playlist as well as from the PlayedSongsArray. I'm not sure how the songs are indexed because you mentioned the problem of reordering tracks. But if you manage arrays with songs' indexes and not just the songs' positions in the playlist, this should work just fine I think.

From captbaritone:

I’ll have to think about it a bit to see if we can make it so that going to the “next” track is not an O(n) operation. Using a Set instead of an array should help, but getting the set of unplayed tracks might require checking every track to see if it’s in the unplayed set.