log entry ID: .....a... 2024-01-11 15:51:35 EET
I had just submitted my application to the Univsity of Helsinki, and had been waiting for the result. So, with nothing else to do, I had decided to do something a little unusual. Over the past 20 years or so, I have collected 4992 tracks of music. And I had decided to systematically listen to literally all of it, at random. That was about a week ago, and I’m now on song number 1189.
This was actually not as easy to do as one would think. I could have set a music player to randomly play all of the songs in my music folders. The first problem is that bad music players do not keep track of which tracks it has already played. That means that after having heard half of the tracks, the odds are only 50-50 that I’ll hit a song I haven’t heard already. When I’m 99% of the way through, the odds of the next song being new will drop to only 1%!! When I have finally listened to all but the last track, there will only be a 1 in 4992 chance that the next random track choice will be the right one. It’d be a long-ass time before I’d have finally heard them all.
In fact, let’s actually calculate how long it would take.
Ffffuck, why do I do this to myself? I do arguably have other things to do…
furious two-hour-long mathematical montage ensues
One solution is to calculate the expected number of tries to randomly choose a unique track, given that nseen
unique tracks have already been played.
The probability of hearing a unique track is (ntracks - nseen)/ntracks
, where ntracks
is the total number of unique tracks.
That makes the expected value ntracks/(ntracks - nseen)
.
Add up all of those expected values for every nseen
, and you get
avg_tries = ntracks * sum from a=1 to ntracks (1/a)
Wow! That is actually quite awesome! This is the first time I’ve ever used a sum over a harmonic sequence in a “serious” problem. Well, that’s a simple calculation.
ghci> [1..4992] & map (\x -> 1/x) & sum & (*4992)
45391.795397460846
ghci>
There. It would take an average of about 45000 tries to hit every track at least once. That’s about ten times longer than without repeats. On top of the extra time, it just really sucks having to hear repeats over and over like that.
Good music players like quodlibet keep track of which tracks it has played in a random session, making sure not to play a track that it has already played this session. That is good, but it is too fragile. The first time one asks quodlibet to deviate from random play, it deletes the random session that is underway.
My solution was to abandon the conventional UI-based music players altogether (sorry, quodlibet) and unix together an alternative solution. I made a random playlist containing every track in my library exactly once. While I was at it, I made it so that the solution would work over the network, so that I could stream my playlist anywhere.
First, I used find
to construct a list of all of my tracks, with one track per line.
> cd /tmp
> find ~/music ~/music-archived -type f -regextype egrep -regex '.*\.(ogg|opus|m4a|mp4|flac)' >all-music
> head all-music
music/The Buggles - 1980 - The Age Of Plastic/10. Technopop.ogg
music/The Buggles - 1980 - The Age Of Plastic/09. Island.ogg
music/The Buggles - 1980 - The Age Of Plastic/06. Elstree.ogg
music/The Buggles - 1980 - The Age Of Plastic/11. Johnny On The Monorail (A Very Different Version).ogg
music/The Buggles - 1980 - The Age Of Plastic/01. Living In The Plastic Age.ogg
music/The Buggles - 1980 - The Age Of Plastic/04. I Love You (Miss Robot).ogg
music/The Buggles - 1980 - The Age Of Plastic/05. Clean, Clean.ogg
music/The Buggles - 1980 - The Age Of Plastic/08. Johnny On The Monorail.ogg
music/The Buggles - 1980 - The Age Of Plastic/03. Kid Dynamo.ogg
music/The Buggles - 1980 - The Age Of Plastic/02. Video Killed The Radio-Star.ogg
>
Then I used sort --random-sort
to randomise the playlist.
> sort --random-sort all-music >music-randomised
> head music-randomised
music-archived/FF7 OST/Disc 2/17 - Mark of the Traitor.mp3
music-archived/Dvorak - The Masterworks/CD07_Symphony 9, Scherzo/02- Symphony No.9, Op.95 'From the New World' - Largo.mp3
music-archived/Wide Mouth Mason - My Old Self.mp3
music/Super Furry Animals/Love Kraft/04 Ohio Heat.mp3
music-archived/Twisted Sister- We're Not Gonna Take It.mp3
music/Claude Debussy - The Complete Works/CD 26/02. Diane au bois, L. 48: 'La divine musique !' (Diane).opus
music/Claude Debussy - The Complete Works/CD 11/13. Camille Saint-Saëns: Étienne Marcel, airs de ballet (transcr. C. Debussy 1890) - II. Entrée des écoliers.opus
music/Claude Debussy - The Complete Works/CD 16/05. Images pour orchestre, L 118a - II. Ibéria (1905-08) - Les parfums de la nuit.opus
music-archived/System of a Down/Steal This Album/Nüguns.mp3
music/Dance Mix '96/04. Gusto - Disco’s Revenge.ogg
>
ASIDE: Oh, shit, Finlandia just came on!
Then, I used fish
’s totally awesome command substitution and a custom tool of my own creation to turn each line into a working HTTP link:
> share (cat music-randomised) > ~/blog/.....a.../music.m3u
> head ~/blog/.....a.../music.m3u
https://toombs.earth/music-archived/FF7%20OST/Disc%202/17%20-%20Mark%20of%20the%20Traitor.mp3
https://toombs.earth/music-archived/Dvorak%20-%20The%20Masterworks/CD07_Symphony%209%2C%20Scherzo/02-%20Symphony%20No.9%2C%20Op.95%20%27From%20the%20New%20World%27%20-%20Largo.mp3
https://toombs.earth/music-archived/Wide%20Mouth%20Mason%20-%20My%20Old%20Self.mp3
https://toombs.earth/music/Super%20Furry%20Animals/Love%20Kraft/04%20Ohio%20Heat.mp3
https://toombs.earth/music-archived/Twisted%20Sister-%20We%27re%20Not%20Gonna%20Take%20It.mp3
https://toombs.earth/music/Claude%20Debussy%20-%20The%20Complete%20Works/CD%2026/02.%20Diane%20au%20bois%2C%20L.%2048%3A%20%27La%20divine%20musique%20%21%27%20%28Diane%29.opus
https://toombs.earth/music/Claude%20Debussy%20-%20The%20Complete%20Works/CD%2011/13.%20Camille%20Saint-Sa%C3%ABns%3A%20%C3%89tienne%20Marcel%2C%20airs%20de%20ballet%20%28transcr.%20C.%20Debussy%201890%29%20-%20II.%20Entr%C3%A9e%20des%20%C3%A9coliers.opus
https://toombs.earth/music/Claude%20Debussy%20-%20The%20Complete%20Works/CD%2016/05.%20Images%20pour%20orchestre%2C%20L%20118a%20-%20II.%20Ib%C3%A9ria%20%281905-08%29%20-%20Les%20parfums%20de%20la%20nuit.opus
https://toombs.earth/music-archived/System%20of%20a%20Down/Steal%20This%20Album/N%C3%BCguns.mp3
https://toombs.earth/music/Dance%20Mix%20%2796/04.%20Gusto%20-%20Disco%E2%80%99s%20Revenge.ogg
>
This playlist works in mpv out of the box:
> mpv music.m3u
Playing: https://toombs.earth/music-archived/FF7%20OST/Disc%202/17%20-%20Mark%20of%20the%20Traitor.mp3
[ffmpeg/demuxer] mp3: Estimating duration from bitrate, this may be inaccurate
(+) Audio --aid=1 (mp3 2ch 44100Hz)
File tags:
Artist: Nobuo Uematsu
Album: Final Fantasy VII Original SoundTrack, Disc 2
Genre: soundtrack
Title: Mark of the Traitor
Track: 17
AO: [pipewire] 44100Hz stereo 2ch floatp
A: 00:00:02 / 00:03:30 (1%) Cache: 207s/7MB
To make it easier to resume playback, I told it to display the playlist item number when it starts a new song. So, now if I ever had to stop mpv, I would be able to resume it where I left off. I also added a couple other conveniences. Here is an example of restarting at track 1206.
> mpv --no-video --term-playing-msg='Playlist position: ${playlist-pos}' --replaygain=track --playlist-start=1206 music.m3u
Playing: https://toombs.earth/music-archived/Opeth/Still%20Life/06%20Serenity%20Painted%20Death.mp3
(+) Audio --aid=1 (mp3 2ch 44100Hz)
File tags:
Artist: Opeth
Album: Still Life
Date: 1999
Genre: Death Metal
Title: Serenity Painted Death
Track: 6
AO: [pipewire] 44100Hz stereo 2ch floatp
Playlist position: 1206
A: 00:00:06 / 00:09:13 (1%) Cache: 547s/31MB
Now that the particular shuffling that I have arbitrarily decided to listen to has been saved to a file, repeats are guaranteed not to happen.
Listening to my music this way has some interesting unintended consequences.
Well, actually, I didn’t really have any intended consequences…
Listening to my music this way has some interesting consequences. Since I know, for a fact, that every song is in that list,
So, this is becoming a good way of determining what my actual favourite songs of all time are. If I can actually remember whether I heard a particular song already since I began this experiment, then I know it’s a good one. I know for sure if it’s an all-time favourite if I can actually remember what I was doing when it came on.
Also, I often acquire some music, then forget I even did so. There’s a lot of stuff in my library I have never even listened to before. Well, I’m listening them it now.
I always thought it would be fun hosting an internet radio station, but I couldn’t stand the idea of transcoding lossy audio files into a single also-lossy audio channel—an act that I consider quite abusive. That poor music, all forced to look and behave the same way, then crammed together into just one file and sent overseas to God knows where…
But if I could just stream a playlist, like music.m3u, which people would play using mpv, that would solve this problem. A wide variety of different audio formats could all be streamed without any transcoding. All of the little tracks would be free to be themselves! It makes me wonder what would happen if one pointed mpv to a playlist at a dynamic HTTP endpoint that generates one entry every time the track is supposed to be advanced. Is mpv smart enough to keep downloading the playlist data? Will it time out? What would be the playlist’s data transfer rate? Will I finally be able to use millibytes per second in a “serious” engineering problem? Well, maybe I’ll investigate this possibility another day…