diff Syncopation models/synpy/TMC.py @ 45:6e9154fc58df

moving the code files to the synpy package directory
author christopherh <christopher.harte@eecs.qmul.ac.uk>
date Thu, 23 Apr 2015 23:52:04 +0100
parents
children 9a60ca4ae0fb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Syncopation models/synpy/TMC.py	Thu Apr 23 23:52:04 2015 +0100
@@ -0,0 +1,85 @@
+'''
+Author: Chunyang Song
+Institution: Centre for Digital Music, Queen Mary University of London
+
+'''
+
+from basic_functions import get_H, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category
+from parameter_setter import are_parameters_valid
+
+# The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level.
+def get_metricity(binarySequence, H):
+	metricity = 0
+	for m in range(len(binarySequence)):
+		metricity = metricity + binarySequence[m]*H[m]
+	return metricity
+
+# The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence.
+def get_max_metricity(binarySequence, H):
+	maxMetricity = 0
+	H.sort(reverse=True) # Sort the metrical weight sequence from large to small
+	for i in range(sum(binarySequence)):
+		maxMetricity = maxMetricity+H[i]
+	return maxMetricity
+
+# find the metrical level L that contains the same number of metrical positions as the length of the binary sequence
+# if the given Lmax is not big enough to analyse the given sequence, request a bigger Lmax
+def find_L(rhythmSequence, Lmax, weightSequence, subdivisionSequence):
+	L = Lmax
+
+	# initially assuming the Lmax is not big enough
+	needBiggerLmax = True 
+	
+	# from the lowest metrical level (Lmax) to the highest, find the matching metrical level that 
+	# has the same length as the length of binary sequence  
+	while L >= 0:
+		if len(get_H(weightSequence,subdivisionSequence, L)) == len(rhythmSequence):
+			needBiggerLmax = False
+			break
+		else:
+			L = L - 1
+
+	# if need a bigger Lmax, print error message and return None; otherwise return the matching metrical level L
+	if needBiggerLmax:
+		print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
+		L = None
+	
+	return L
+
+# The get_syncopation function calculates the syncopation value of the given sequence for TMC model. 
+#def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
+def get_syncopation(bar, parameters = None):
+	syncopation = None
+	binarySequence = bar.get_binary_sequence()
+	subdivisionSequence = bar.get_subdivision_sequence()
+
+	if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
+		print 'Warning: TMC model detects polyrhythms so returning None.'
+	else:
+		
+		# set the defaults
+		Lmax  = 5
+		weightSequence = range(Lmax+1,0,-1) # i.e. [6,5,4,3,2,1]
+		
+		if parameters!= None:
+			if 'Lmax' in parameters:
+				Lmax = parameters['Lmax']				
+			if 'W' in parameters:
+				weightSequence = parameters['W']
+
+		if not are_parameters_valid(Lmax, weightSequence, subdivisionSequence):
+			print 'Error: the given parameters are not valid.'
+		else:
+			binarySequence = velocity_sequence_to_min_timespan(binarySequence)	# converting to the minimum time-span format
+			L = find_L(binarySequence, Lmax, weightSequence, subdivisionSequence) 
+			if L != None:
+				#? generate the metrical weights of the lowest level, 
+				#? using the last matching_level number of elements in the weightSequence, to make sure the last element is 1
+				H = get_H (weightSequence[-(L+1):], subdivisionSequence, L)
+				metricity = get_metricity(binarySequence, H)	# converting to binary sequence then calculate metricity
+				maxMetricity = get_max_metricity(binarySequence, H)
+
+				syncopation = maxMetricity - metricity
+				
+	return syncopation
+