mmcirvin: (Default)
[personal profile] mmcirvin
A while back I opined that iTunes ratings were essentially useless, mostly because there's no way I'm going to go and manually rate every song in my library; then I started thinking about ways that they might be made useful. I have a lot of Smart Playlists and such that are based on play counts, but play counts have the problem that they penalize long classical and jazz pieces that I actually like quite a lot. I don't necessarily listen to them as many times, because they're long, but going by time spent listening to them, they get their due. So an auto-rating script that depended on time spent listening might be a useful way to do the initial population of the library with ratings, at least as a starting point.

It couldn't be a linear scale, since the distribution of songs I listen to is probably so sharply peaked that it would blow out the scale. A logarithmic scale seemed reasonable. But as far as I can tell AppleScript has no real math library (Apple's FAQ answers the question "how do I use trigonometry?" by listing a bunch of Taylor-series-based AppleScript implementations of trig functions; gee, thanks a lot). So I had to improvise with a crude function that basically linearly interpolates between powers of the base.

Anyway, here was what I came up with:

on poorMansLogarithm(x)
	
	set lowBound to 1
	set factor to 2
	set answer to 0
	
	repeat 100 times
		if x > lowBound then
			set answer to answer + 1
		else
			set answer to answer + ((x - lowBound / factor) / (lowBound - lowBound / factor))
			return answer
		end if
		set lowBound to lowBound * factor
	end repeat
	return answer
	
end poorMansLogarithm

tell application "iTunes"
	set tunes to the selection of the front browser window
	
	set maxTimePlayed to 0
	set minTimePlayed to (duration of item 1 of tunes) * (played count of item 1 of tunes)
	set minTimePlayedCutoff to 30
	
	repeat with i from 1 to count of tunes
		set currentTrack to item i of tunes
		set timePlayed to (duration of currentTrack) * (played count of currentTrack)
		if (timePlayed > maxTimePlayed) then set maxTimePlayed to timePlayed
		if (timePlayed < minTimePlayed) then set minTimePlayed to timePlayed
	end repeat
	
	if (minTimePlayed < minTimePlayedCutoff) then set minTimePlayed to minTimePlayedCutoff
	
	set maxRating to my poorMansLogarithm(maxTimePlayed)
	set minRating to my poorMansLogarithm(minTimePlayed)
	set ratingScale to 115.0 / (maxRating - minRating)
	
	repeat with i from 1 to count of tunes
		set currentTrack to item i of tunes
		set timePlayed to (duration of currentTrack) * (played count of currentTrack)
		set newRating to my poorMansLogarithm(timePlayed)
		set newRating to (newRating - minRating) * ratingScale
		if (newRating > 100) then set newRating to 100
		if (newRating < 0) then set newRating to 0
		set rating of currentTrack to newRating
	end repeat
end tell



It's not very efficient and takes several minutes to rate my library. But it does all right. There are some weird tweaks in there. Interestingly, the rating is actually represented internally as a number from 0 to 100. But the maximum rating of 5 stars is only given to songs rated exactly 100, so I scaled up the range a little and then clipped to 100 afterwards to give the 5 stars to a few more songs. Also, there's a minimum cutoff in there to keep stuff I haven't listened to at all from skewing the curve.

Of course, these ratings are penalizing newer music that I haven't had the time to listen to a lot. It's only intended as a start.

Date: 2005-03-13 08:54 pm (UTC)
From: [identity profile] mmcirvin.livejournal.com
By the way, to preemptively answer the comments you haven't written yet, I'm perfectly aware that there are dozens of ways I could optimize this. However, I don't care much.

Date: 2005-03-14 12:39 am (UTC)
ext_8707: Taken in front of Carnegie Hall (picassohead)
From: [identity profile] ronebofh.livejournal.com
Too bad AppleScript doesn't work in Windows...

Date: 2005-03-14 04:58 am (UTC)
From: [identity profile] mmcirvin.livejournal.com
Yeah, in iTunes, that's actually the biggest thing that Apple keeps reserved for the Mac people. Of course 99% of iTunes users won't care.

I actually sort of dislike AppleScript as a language; it has a COBOLesque verbosity to it. The idea of a programming language with an internationalizable command vocabulary is kind of interesting, though.

Date: 2005-03-14 05:04 am (UTC)
From: [identity profile] mmcirvin.livejournal.com
I did get an idea about how to make it better: use the date-added field to compensate for the newness of the track somehow. Maybe the correct number to use is the fraction of the time since ripping that I've actually spent listening to the piece. On the other hand, that would penalize pieces that sat around unloved until I belatedly discovered them through shuffle play, one of the great benefits of digital music.

Date: 2005-03-14 05:23 am (UTC)
ckd: small blue foam shark (Default)
From: [personal profile] ckd
Neat idea.

I rate on-the-fly using Synergy, so while there will be unrated songs in my library, I generally rate them as I hear them (and have Smart Playlists set to make sure they're on my usual playlists).

Date: 2005-03-14 06:39 pm (UTC)
From: [identity profile] mmcirvin.livejournal.com
A while back I went looking for something like this in the Doug's AppleScripts for iTunes (http://www.malcolmadams.com/itunes/index.php) archive, but the only rating scripts in there are ones that either nag you or attempt to assist you to rate songs manually.

Now that I've got a rough set of ratings, it should make sense to use them as criteria in Smart Playlists and such. Up to now I haven't done so.

Date: 2005-03-14 05:42 am (UTC)
From: [identity profile] iayork.livejournal.com
I'm perfectly aware that there are dozens of ways I could optimize this. However, I don't care much.

Stopped me in time. Do note "do shell script", though, as a potentially easy was of calculating logs.

I find I never use ratings, though it seems like I should. At one time I thought about using them as code for some other factor -- I was starting with the idea of rating Pop music with 5-star-high, and Classical with 1-star-high, and wondered about using some variant making use of the 1 through 100 internal ranking ... but never got around to it, or even formulated the idea properly.

Date: 2005-03-14 06:48 am (UTC)
From: [identity profile] mmcirvin.livejournal.com
Yeah, I thought about using an external math engine, either via "do shell script" or harnessing some scriptable math app. Doing it with a line of shell is probably best, but I was also taking the opportunity to learn a little more AppleScript by hacking up my silly log interpolator. (Also, of course if I really needed a home-grown logarithm I'd combine my approach with the Taylor series for the interpolation. I was going to just use a Taylor but had forgotten that the Taylor series of ln is only convergent in a small neighborhood.)

June 2025

S M T W T F S
1234567
89101112 1314
151617181920 21
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 17th, 2025 04:39 am
Powered by Dreamwidth Studios