view Syncopation models/TOB_v2.py @ 0:76ce27beba95

Have uploaded the syncopation dataset and audio wavefies.
author Chunyang Song <csong@eecs.qmul.ac.uk>
date Fri, 21 Mar 2014 15:49:46 +0000
parents
children
line wrap: on
line source
'''
Author: Chunyang Song
Institution: Centre for Digital Music, Queen Mary University of London

** Offbeat-ness Model - Version 2, not adopting time span **

Algorithm:

Fix the 4/4 rhythm to 16-unit circle, 6/8 or 3/4 rhythm to 12-unit circle.

Calculate on-beat positions in the metrical circle: positions can divide the circle equally with divisor(s), 1< divisor < N
Define the onset not locating the on-beat positions the off-beat note;
Syncopation is the total number of off-beat onsets.

'''

from MeterStructure import MeterStructure

def onBeatPos(circle):
	l = len(circle)
	divisors = []
	for i in range(2,l):
		if l%i ==0:
			divisors.append(i)

	onBeat = []
	for d in divisors:
		for pos in circle:
			if pos%d == 0:
				onBeat.append(pos)

	return onBeat	

def offBeatNess(rhythm, time_sig, category, bar):
	ms = MeterStructure(time_sig)
	circle = ms.getCircle(bar)

	if len(circle)!=0:
		# Calculate on-beat positions within one bar
		onBeat = onBeatPos(ms.getCircle())
		
		onBeat.sort() # sort the on-beat positions. This list will have duplicate numbers, but it doesn't affect the following algorithm
		
		# Calculate how many onsets are off-beat, which represent syncopation
		syncopation = 0
		
		l = len(rhythm) 
		for i in range(l):
			if rhythm[i] == 1: # onset detected
				pos = (float(i)/l)*len(circle) # looking for the metrical position where this note locates
				if pos >= len(circle)/2:
					pos = pos- len(circle)/2
				if pos in onBeat:
					continue
				else:
					syncopation = syncopation + 1 
				
		return syncopation	
	else:
		return -1


# Retrieve the stimuli
#f = file('stimuli.txt')
f = file('stimuli_34only.txt')

#Calculate syncopation for each rhythm pattern
while True:
	line = f.readline().split(';')
	if len(line) == 1:
		 break
	else:
		sti_name = line[0]
		rhythmString = line[1].split()
		time_sig = line[2]
		category = line[3]
		bar = int(line[4])
		
		rhythm = map(int,rhythmString[0].split(','))

		print sti_name, offBeatNess(rhythm, time_sig, category, bar)