# Beats Distribution

When another post on Jive Junction’s Facebook group asked about BPMs for lindy hop parties, I decided to check the distribution from recent saved DJed playlists, 14 in total. These include two from big events (Lindy Shock, Vintage Swing Festival), three from local (to Slovenia) events, and the rest are weekly local dance nights in Tel Aviv and Ljubljana. Here’s the plot:

$\mu=146, \sigma=17.1$

Except for the peak in the middle, the distribution is pretty normal. When I DJ, I try to match the speed to what I think will get the most dancers on the floor, in the current song and the next. Over time, I have consciously come to think that 146 is the most ideal BPM for this task – whether after a fast song or a slow song, or even of the same speed, it will bring out the most dancers for this and the next song.

But I haven’t really documented how many people are dancing to each song, and maybe I have it off. So I’ve now started, and I will also randomise my playlists a bit more with the help of a computer, which hopefully is unbiased. I definitely want to try Shana Worel’s suggestion of $\mu=170,\sigma=16.6$ for a few sessions (“with a few outliers sprinkled in for good measure”).

It would be pretty cool to get a result similar to that well known experiment in the west coast world. 122 was it?

————————–

The above plot was made using a python script that I wrote, that goes over playlists in the iTunes Media Library file. This is an xml file, which on my mac was found in ‘~/Music/iTunes/’. You can run the script as well to see your own statistics. If there are playlists that are not relevant, you can name them and the script will disregard them. I used numpy and matplotlib to generate the plot, and those few lines are not included.

from xml.dom.minidom import parse, parseString
from math import sqrt

# Change this to wherever your 'iTunes Music Library.xml' is.
_itunes = &quot;~/Music/iTunes/iTunes Music Library.xml&quot;

# Irrelevant playlists. For example, the bpms from my
# wedding playlist should not be counted.
irrelevant = ['April','From Videos','Wedding!','WeirdThing']

###########################################################
###########################################################

itunes = parse(_itunes)

_tracks = itunes.childNodes[1].childNodes[1].childNodes[24]
_playlists = itunes.childNodes[1].childNodes[1].childNodes[28]

def getKeyIndex(idict, key):
cn = idict.childNodes
for i in range(len(cn)):
if cn[i].hasChildNodes() and cn[i].tagName == u'key' and cn[i].childNodes[0].data == key:
return i
return -1

def getValue(idict, key):
i = getKeyIndex(idict, key)
if i != -1:
cn = idict.childNodes
i = i+1
while not cn[i].hasChildNodes():
i = i+1
if i &gt;= len(cn):
return -1
return cn[i].childNodes[0].data
return -1

# Parse tracks
tracks = {}
for track in _tracks.childNodes:
if track.hasChildNodes() and track.tagName == u'dict':
id = int(track.childNodes[2].childNodes[0].data)
bpm = int(getValue(track, u'BPM'))
tracks[id] = (bpm,)

# Parse playlists
playlists = {}
for playlist in _playlists.childNodes:
badtags = ['Distinguished Kind','Smart Info', 'Folder', 'Master']
name = getValue(playlist, 'Name')
itemsIndex = getKeyIndex(playlist, 'Playlist Items')

if set([getKeyIndex(playlist, tag) for tag in badtags]) == set([-1]) and name != -1 and itemsIndex != -1:
while not playlist.childNodes[itemsIndex].hasChildNodes() or playlist.childNodes[itemsIndex].tagName != u'array':
itemsIndex += 1
if itemsIndex &gt;= len(playlist.childNodes):
break

if itemsIndex &gt;= len(playlist.childNodes):
continue

ptracks = [int(i.childNodes[0].data) for i in playlist.childNodes[itemsIndex].getElementsByTagName('integer')]

playlists[name] = ptracks

for irr in irrelevant:
playlists.pop(irr)

allbpms = []
for p in playlists:
for id in playlists[p]:
if tracks[id][0] &gt; 0:
allbpms.append(tracks[id][0])

mu = (sum(allbpms)+0.0)/len(allbpms)
sigma = sqrt(sum([(x-mu)**2 for x in allbpms])/len(allbpms))

print 'mu:', mu
print 'sigma:', sigma