I geeked again this weekend. I wanted to solve a music problem i'd been having. I have a car mp3 cd player that can take a 700mb CDRW and play in 3 modes: sequential (start in first folder alphabetically, play whole disc in order), random folder (play tracks within one folder and sub-folders in random order), and random disc (play tracks from anywhere on the CD in random order). My music collection is organized with iTunes, and everything is properly set (including genre, song name, artist, album, track #, rated 1-5 stars).
The problem was that even though I had a rated collection, I couldn't easily burn a 700mb worth of tunes to listen to that could play 5 songs through without me needing to do some serious skipping. This was due to my collection being unreasonably large, and my music taste being unreasonably broad. What'd invariably happen would be that i'd get all the 01. xxxx 01. yyyyy 01. zzzz tracks in a row, which was tedious; or, if I put random mode on i'd get all 3-5 star songs but they wouldn't go with each other -- i'd hear heavy dream theater followed by classical gustav holst. Both have tracks that I rate at 5 stars, but no way I wanna hear them next to each other. Also, randomly picking stuff would often end up with 100 techno songs in a row when I was in the mood for classic rock, or vice-versa.
So, I did what anyone would do - spent way longer than I should have writing a perl script when I could have done it in Java in a quarter of the time, or C++ in half the time. Ah, that'll show me. Took long because even though i've used'em many times, I'm still not comfortable enough to remember the syntaxes for addressing and manipulating hashes of hashes or arrays of arrays .. perl is nitpicky.
1. leverage the ability of my car deck's random play
2. burn a mix mp3 cd that can be played without needing to skip tracks
Define a cumulative ratio for genres. Ok so that makes no sense, cuz it's late and i can't figure out how you explain it, but it looks like this... you take all the genres in your collection, and you assign them a number. All the numbers add up to 100, ie. 100%. Next, have a program that takes two input parameters - the number of CDs you're making, and the size of each (so you can populate keyfobs like my wife's instead if you want)... the script grabs X mb of files (say 700) and it does it Y times, but in the percentages you told it to. So if you give pop 5% and indie rock 15%, on a 700mb CD you get 700mb * 5% = 35mb of pop, and 700mb * 15% = 105mb of indie rock. Then, take all these tunes and put them in a folder structure on the disc that's genre-based, so your mp3 cd looks like:
G:\ G:\alternative G:\indie rock G:\rock G:\techno... etc.
- I can turn random disc mode (on car deck) on, and be likely to only hear songs that fit well together; this is because i've given a percentage of 0% to classical and spoken word etc, because they don't fit into random compilations at all. I don't ever get 100 techno songs in a row, because the percentage i've given to techno is representative of how often I want to hear it
- if i'm in the mood for a specific genre, I can turn random folder mode on and select a folder. That way if I want to hear all techno, i just browse to the folder and i'm guaranteed to get all good techno, randomized
- if i'm in the mood for one genre after another, I can turn random mode off altogether, and get the genres in order. Skipping folders is easy with my deck so the order isn't forced.
Oh, and when I use it to make more than one disc at a time, it's careful not to allow dupes between them, so you can use this to randomly segregate your collection into comps, weighted by genre. I also added an ability to skip long songs (default is 5m30s max), easily configurable.
My iTunes doesn't do a good job of normalizing song volumes at all, even with the option properly turned on and allowing it to spend all night crunching through my collection. My fix is to use mp3gain which normalizes by "loudness" not by peak value, a cool algorithm some PhD d00d thought up. I realize that iTunes can burn CDs and it can probably burn random ones, but I just didn't see a way to pick X mb of stuff randomly with a constant ratio of genres, multiple times.
So how would you actually use this script? Easy, presuming you have all your genres set your songs rated. First, configure your desired genres: edit the script and scroll down to the part with the numbers. It's pretty obvious what to do here, but there's one important note: you must have an entry in the script for every genre iTunes has a song for. Otherwise the script'll barf and die gracefully. Oh, and don't forget your numbers have to add to 100%! Next, pop open iTunes, and browse to a large selection of songs you want. I suggest creating a smart playlist that only picks songs that are rated 3-5 stars, but you can just use My Top Rated which does 4-5 stars. In the bottom list (with all genres all artists all albums selected) of all the gooey gigs of goodness, hit cntrl-A to select'em all, and right-click and select "Copy". Browse somewhere w/ windows explorer on an HD with enough space to copy'em all, and paste away. You can put them all in one folder (easiest), or you can copy them from various places without itunes and have folders, doesn't matter (my script recurses subdirs). Then, run the script in the dir that has your songs or dirs of songs, and specify the two parameters (number of CDs, number of MB per CD). It'll read all the tags first, then create ../newCD# where # will be 1, 2, 3... to whatever you set as the first parameter. Inside each will be subdirs of your genres. Lastly, open up mp3gain (google it if you don't got it) and do track analysis then track gain (I recommend setting the desired gain to 94 dB). Done, burn'em!
If you want to download and use it, click here. Note that i've included a .EXE copy so that windows users don't have to mess with installing ActivePerl or whatever.