changeset 26:d9d22e6f396d

fixed SG!
author csong <csong@eecs.qmul.ac.uk>
date Sun, 12 Apr 2015 15:53:58 +0100
parents df1e7c378ee0
children ed29ed80635c
files Syncopation models/SG.py Syncopation models/basic_functions.py
diffstat 2 files changed, 62 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/Syncopation models/SG.py	Sun Apr 12 13:06:17 2015 +0100
+++ b/Syncopation models/SG.py	Sun Apr 12 15:53:58 2015 +0100
@@ -4,7 +4,7 @@
 
 '''
 
-from basic_functions import get_H, velocity_sequence_to_min_timespan, get_rhythm_category
+from basic_functions import get_H, velocity_sequence_to_min_timespan, get_rhythm_category, upsample_velocity_sequence
 from TMC import find_L
 
 #def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
@@ -16,7 +16,7 @@
 	if get_rhythm_category(velocitySequence, subdivisionSequence) == 'poly':
 		print 'Warning: SG model detects polyrhythms so returning None.'
 	else:
-		velocitySequence = velocity_sequence_to_min_timespan(velocitySequence)	# converting to the minimum time-span format
+		#velocitySequence = velocity_sequence_to_min_timespan(velocitySequence)	# converting to the minimum time-span format
 
 		# If the parameters are not given, use the default settings
 		if parameters == None:
@@ -30,59 +30,56 @@
 				pass
 				#raise InvalidParameterError
 
-		L = find_L(velocitySequence, Lmax, weightSequence, subdivisionSequence) 
-		print 'L', L
-		if L != None:
-			syncopation = 0
-			# generate the metrical weights of the lowest level
-			H = get_H(weightSequence,subdivisionSequence, L)
-			print 'H', H
+		syncopation = 0
+		# generate the metrical weights of level Lmax, and upsample(stretch) the velocity sequence to match the length of H
+		H = get_H(weightSequence,subdivisionSequence, Lmax)
+		velocitySequence = upsample_velocity_sequence(velocitySequence, len(H))
 
-			# The ave_dif_neighbours function calculates the (weighted) average of the difference between the note at a certain index and its neighbours in a certain metrical level
-			def ave_dif_neighbours(index, level):
+		# The ave_dif_neighbours function calculates the (weighted) average of the difference between the note at a certain index and its neighbours in a certain metrical level
+		def ave_dif_neighbours(index, level):
 
-				averages = []
-				parameterGarma = 0.8
-				
-				# The findPre function is to calculate the index of the previous neighbour at a certain metrical level.
-				def find_pre(index, level):
-					preIndex = (index - 1)%len(H)	# using % is to restrict the index varies within range(0, len(H))
-					while(H[preIndex] > level):
-						preIndex = (preIndex - 1)%len(H)
-					print 'preIndex', preIndex
-					return preIndex
+			averages = []
+			parameterGarma = 0.8
+			
+			# The findPre function is to calculate the index of the previous neighbour at a certain metrical level.
+			def find_pre(index, level):
+				preIndex = (index - 1)%len(H)	# using % is to restrict the index varies within range(0, len(H))
+				while(H[preIndex] > level):
+					preIndex = (preIndex - 1)%len(H)
+				#print 'preIndex', preIndex
+				return preIndex
 
-				# The findPost function is to calculate the index of the next neighbour at a certain metrical level.
-				def find_post(index, level):
-					postIndex = (index + 1)%len(H)
-					while(H[postIndex] > level):
-						postIndex = (postIndex + 1)%len(H)
-					print 'postIndex', postIndex
-					return postIndex
-				
-				# The dif function is to calculate a difference level factor between two notes (at note position index1 and index 2) in velocity sequence
-				def dif(index1,index2):
-					parameterBeta = 0.5
-					dif_v = velocitySequence[index1]-velocitySequence[index2]
-					dif_h = abs(H[index1]-H[index2])
-					dif = dif_v*(parameterBeta*dif_h/4+1-parameterBeta)
-					print 'dif', dif
-					return dif
+			# The findPost function is to calculate the index of the next neighbour at a certain metrical level.
+			def find_post(index, level):
+				postIndex = (index + 1)%len(H)
+				while(H[postIndex] > level):
+					postIndex = (postIndex + 1)%len(H)
+				#print 'postIndex', postIndex
+				return postIndex
+			
+			# The dif function is to calculate a difference level factor between two notes (at note position index1 and index 2) in velocity sequence
+			def dif(index1,index2):
+				parameterBeta = 0.5
+				dif_v = velocitySequence[index1]-velocitySequence[index2]
+				dif_h = abs(H[index1]-H[index2])
+				dif = dif_v*(parameterBeta*dif_h/4+1-parameterBeta)
+				#print 'dif', dif
+				return dif
 
-				# From the highest to the lowest metrical levels where the current note resides, calculate the difference between the note and its neighbours at that level
-				for l in range(level, max(H)+1):
-					ave = (parameterGarma*dif(index,find_pre(index,l))+dif(index,find_post(index,l)) )/(1+parameterGarma)
-					averages.append(ave)
-				print 'averages', averages
-				return averages
+			# From the highest to the lowest metrical levels where the current note resides, calculate the difference between the note and its neighbours at that level
+			for l in range(level, max(H)+1):
+				ave = (parameterGarma*dif(index,find_pre(index,l))+dif(index,find_post(index,l)) )/(1+parameterGarma)
+				averages.append(ave)
+			#print 'averages', averages
+			return averages
 
-			# Calculate the syncopation value for each note
-			for index in range(len(velocitySequence)):
-				if velocitySequence[index] != 0: # Onset detected
-					h = H[index] 
-					# Syncopation potential according to its metrical level, which is equal to the metrical weight
-					potential = 1 - pow(0.5,h)
-					level = h 		# Metrical weight is equal to its metrical level
-					syncopation += min(ave_dif_neighbours(index, level))*potential
-			
+		# Calculate the syncopation value for each note
+		for index in range(len(velocitySequence)):
+			if velocitySequence[index] != 0: # Onset detected
+				h = H[index] 
+				# Syncopation potential according to its metrical level, which is equal to the metrical weight
+				potential = 1 - pow(0.5,h)
+				level = h 		# Metrical weight is equal to its metrical level
+				syncopation += min(ave_dif_neighbours(index, level))*potential
+		
 	return syncopation
--- a/Syncopation models/basic_functions.py	Sun Apr 12 13:06:17 2015 +0100
+++ b/Syncopation models/basic_functions.py	Sun Apr 12 15:53:58 2015 +0100
@@ -79,6 +79,18 @@
 				isPrime = False
 	return isPrime
 
+# upsample a velocity sequence to certain length, e.g. [1,1] to [1,0,0,0,1,0,0,0]
+def upsample_velocity_sequence(velocitySequence, length):
+	upsampledVelocitySequence = [0]*length
+	if length%len(velocitySequence) != 0:
+		print 'Error: the velocity sequence can only be upsampled to the interger times of its length.'
+	else:
+		scalingFactor = length/len(velocitySequence)
+		for index in range(len(velocitySequence)):
+			upsampledVelocitySequence[index*scalingFactor] = velocitySequence[index]
+	return upsampledVelocitySequence
+
+
 # convert a velocity sequence to its minimum time-span representation
 def velocity_sequence_to_min_timespan(velocitySequence):
 	minTimeSpanVelocitySeq = [1]
@@ -118,7 +130,6 @@
 	return noteSequence
 
 
-
 # get_note_indices returns all the indices of all the notes in this velocity_sequence
 def get_note_indices(velocitySequence):
 	noteIndices = []
@@ -159,7 +170,7 @@
 	e.g. prime_factors of polyrhythm 100100101010 in 4/4 is [2,3] but subdivision_seq = [1,2,2] for 4/4 
 	'''
 	rhythmCategory = 'mono'
-	for f in find_prime_factors(len(get_min_timeSpan(velocitySequence))):
+	for f in find_prime_factors(len(velocity_sequence_to_min_timespan(velocitySequence))):
 		if not (f in subdivisionSequence): 
 			rhythmCategory = 'poly'
 			break