changeset 21:b6daddeefda9

working on KTH
author csong <csong@eecs.qmul.ac.uk>
date Tue, 07 Apr 2015 23:16:13 +0100
parents b959c2acb927
children 2dbc09ca8013
files Syncopation models/KTH.py Syncopation models/basic_functions.py Syncopation models/music_objects.py Syncopation models/syncopation.py
diffstat 4 files changed, 123 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/Syncopation models/KTH.py	Tue Apr 07 19:05:07 2015 +0100
+++ b/Syncopation models/KTH.py	Tue Apr 07 23:16:13 2015 +0100
@@ -3,7 +3,6 @@
 Institution: Centre for Digital Music, Queen Mary University of London
 
 '''
-## Problems! Note indices, post bar
 
 from basic_functions import get_min_timeSpan, get_note_indices, repeat
 
@@ -40,42 +39,61 @@
 		s = 1
 	return s
 
-# To calculate syncopation value of the sequence in the given time-signature.
-#def get_syncopation(seq, timesig, postbar_seq):
-def get_syncopation(bar, parameter = None):
-	syncopation = 0
+def get_syncopation(bar, parameters):
+	syncopation = None
 
-	numerator = int(timesig.split("/")[0])
-	if numerator == round_down_power_2(numerator):	# if is a binary time-signature
-		# converting to minimum time-span format
-		seq = get_min_timeSpan(seq)	
-		if postbar_seq != None:
-			postbar_seq = get_min_timeSpan(postbar_seq)
+	# KTH only deals with simple-duple meter where the number of beats per bar is a power of two.
+	numerator = bar.get_time_signature().get_numerator()
+	if numerator != round_down_power_2(numerator):
+		print 'Warning: KTH model detects non simple-duple meter so returning None.'
+	else:
+		# retrieve note-sequence and next bar's note-sequence
+		noteSequence = bar.get_note_sequence()
+		nextbarNoteSequence = None
+		if bar.get_next_bar() != None:
+			nextbarNoteSequence = bar.get_next_bar().get_note_sequence()
 
-		# sf is a stretching factor matching rhythm sequence and meter, as Keith defines the note duration as a multiple of 1/(2^d) beats where d is number of metrical level
-		sf = round_up_power_2(len(seq))
+		# find the delta_t so that the time-span (in ticks) is minimized and the note durations are represented by possible smallest numbers
+		# delta_t is the greatest common divisor of all the note durations
+
+
+
+
+# # To calculate syncopation value of the sequence in the given time-signature.
+# def get_syncopation(seq, timesig, postbar_seq):
+# 	syncopation = 0
+
+# 	numerator = int(timesig.split("/")[0])
+# 	if numerator == round_down_power_2(numerator):	# if is a binary time-signature
+# 		# converting to minimum time-span format
+# 		seq = get_min_timeSpan(seq)	
+# 		if postbar_seq != None:
+# 			postbar_seq = get_min_timeSpan(postbar_seq)
+
+# 		# sf is a stretching factor matching rhythm sequence and meter, as Keith defines the note duration as a multiple of 1/(2^d) beats where d is number of metrical level
+# 		sf = round_up_power_2(len(seq))
 		
-		# retrieve all the indices of all the notes in this sequence
-		note_indices = get_note_indices(seq)
+# 		# retrieve all the indices of all the notes in this sequence
+# 		note_indices = get_note_indices(seq)
 
-		for i in range(len(note_indices)):
-			# Assuming start_time is the index of this note, end_time is the index of the following note
-			start_time = note_indices[i]*sf/float(len(seq))
+# 		for i in range(len(note_indices)):
+# 			# Assuming start_time is the index of this note, end_time is the index of the following note
+# 			start_time = note_indices[i]*sf/float(len(seq))
 
-			if i == len(note_indices)-1:	# if this is the last note, end_time is the index of the following note in the next bar
-				if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)):
-					next_index = get_note_indices(postbar_seq)[0]+len(seq)
-					end_time = next_index*sf/float(len(seq))
-				else:	# or if the next bar is none or full rest, end_time is the end of this sequence.
-					end_time = sf
-			else:
-				end_time = note_indices[i+1]*sf/float(len(seq))
+# 			if i == len(note_indices)-1:	# if this is the last note, end_time is the index of the following note in the next bar
+# 				if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)):
+# 					next_index = get_note_indices(postbar_seq)[0]+len(seq)
+# 					end_time = next_index*sf/float(len(seq))
+# 				else:	# or if the next bar is none or full rest, end_time is the end of this sequence.
+# 					end_time = sf
+# 			else:
+# 				end_time = note_indices[i+1]*sf/float(len(seq))
 
-			duration = end_time - start_time
-			c_n = round_down_power_2(duration)
-			syncopation = syncopation + start(start_time,c_n) + end(end_time,c_n)
-	else: 
-		print 'Error: KTH model can only deal with binary time-signature, e.g. 2/4 and 4/4. '
-		syncopation = None
+# 			duration = end_time - start_time
+# 			c_n = round_down_power_2(duration)
+# 			syncopation = syncopation + start(start_time,c_n) + end(end_time,c_n)
+# 	else: 
+# 		print 'Error: KTH model can only deal with binary time-signature, e.g. 2/4 and 4/4. '
+# 		syncopation = None
 
-	return syncopation
+# 	return syncopation
--- a/Syncopation models/basic_functions.py	Tue Apr 07 19:05:07 2015 +0100
+++ b/Syncopation models/basic_functions.py	Tue Apr 07 23:16:13 2015 +0100
@@ -118,6 +118,9 @@
 		print 'Error: a subdivision factor or metrical weight is not defined for the request metrical level.'
 	return H
 
+def calculate_time_span_ticks(numerator, denominator, ticksPerQuarter):
+	return (numerator * ticksPerQuarter *4) / denominator
+
 # # The get_subdivision_seq function returns the subdivision sequence of several common time-signatures defined by GTTM, 
 # # or ask for the top three level of subdivision_seq manually set by the user.
 # def get_subdivision_seq(timesig, L_max):
--- a/Syncopation models/music_objects.py	Tue Apr 07 19:05:07 2015 +0100
+++ b/Syncopation models/music_objects.py	Tue Apr 07 23:16:13 2015 +0100
@@ -1,5 +1,5 @@
 
-from basic_functions import ceiling, string_to_sequence
+from basic_functions import ceiling, string_to_sequence, calculate_time_span_ticks
 
 import parameter_setter 
 import rhythm_parser 
@@ -68,13 +68,13 @@
 		self.prevBar = prevBar
 
 	def get_note_sequence(self):
-		#if self.noteSequence==None:
-		#	self.noteSequence = velocity_sequence_to_notes(self.velocitySequence)
+		if self.noteSequence==None:
+			self.noteSequence = velocity_sequence_to_notes(self.velocitySequence)
 		return self.noteSequence
 
 	def get_velocity_sequence(self):
 		if self.velocitySequence==None:
-			self.velocitySequence = note_sequence_to_velocities(self.velocitySequence)
+			self.velocitySequence = note_sequence_to_velocities(self.noteSequence)
 		return self.velocitySequence
 
 	def get_binary_sequence(self):
@@ -101,9 +101,9 @@
 	def get_time_signature(self):
 		return self.timeSignature
 
-	def get_t_span(self):
-		# return the length of a bar in time units
-		return None # NEED TO IMPLEMENT
+	# return the length of a bar in time units (ticks)
+	def get_time_span(self):
+		return calculate_time_span_ticks(self.timeSignature.get_numerator(),self.timeSignature.get_denominator(), self.ticksPerQuarter)
 
 class TimeSignature():
 	def __init__(self, inputString):
--- a/Syncopation models/syncopation.py	Tue Apr 07 19:05:07 2015 +0100
+++ b/Syncopation models/syncopation.py	Tue Apr 07 23:16:13 2015 +0100
@@ -4,73 +4,77 @@
 
 '''
 
+def sync_perbar_permodel (model, bar, parameters):
+	return model.get_syncopation(bar, parameters)
 
-def sync_perbar_permodel(seq, model, timesig = None, subdivision_seq = None, weight_seq = None, L_max = 5, prebar_seq = None, postbar_seq = None, strong_beat_level = None):
-	syncopation = None
+# def syncopation_barlist_permodel(model, barlist, parameters):
 
-	if seq == None or model == None:
-		print 'Error: please indicate rhythm sequence and syncopation model.'
+# def sync_perbar_permodel(seq, model, timesig = None, subdivision_seq = None, weight_seq = None, L_max = 5, prebar_seq = None, postbar_seq = None, strong_beat_level = None):
+# 	syncopation = None
 
-	elif timesig == None and subdivision_seq == None:
-		print 'Error: please indicate either time signature or subdivision sequence.'
+# 	if seq == None or model == None:
+# 		print 'Error: please indicate rhythm sequence and syncopation model.'
+
+# 	elif timesig == None and subdivision_seq == None:
+# 		print 'Error: please indicate either time signature or subdivision sequence.'
 	
-	else:
-		while subdivision_seq == None:
-			from basic_functions import get_subdivision_seq
-			subdivision_seq = get_subdivision_seq(timesig, L_max)
+# 	else:
+# 		while subdivision_seq == None:
+# 			from basic_functions import get_subdivision_seq
+# 			subdivision_seq = get_subdivision_seq(timesig, L_max)
 
-		# The get_rhythm_category function is used to detect rhythm category: monorhythm or polyrhythm.
-		# For monorhythms, all prime factors of the length of minimum time-span representation of this sequence are
-		# elements of its subdivision_seq, otherwise it is polyrhythm; 
-		# e.g. prime_factors of polyrhythm 100100101010 in 4/4 is [2,3] but subdivision_seq = [1,2,2] for 4/4 
-		def get_rhythm_category():
-			rhythm_category = 'mono'
-			from basic_functions import get_min_timeSpan, find_prime_factors
-			for f in find_prime_factors(len(get_min_timeSpan(seq))):
-				if not (f in subdivision_seq): 
-					rhythm_category = 'poly'
-					break
-			return rhythm_category
+# 		# The get_rhythm_category function is used to detect rhythm category: monorhythm or polyrhythm.
+# 		# For monorhythms, all prime factors of the length of minimum time-span representation of this sequence are
+# 		# elements of its subdivision_seq, otherwise it is polyrhythm; 
+# 		# e.g. prime_factors of polyrhythm 100100101010 in 4/4 is [2,3] but subdivision_seq = [1,2,2] for 4/4 
+# 		def get_rhythm_category():
+# 			rhythm_category = 'mono'
+# 			from basic_functions import get_min_timeSpan, find_prime_factors
+# 			for f in find_prime_factors(len(get_min_timeSpan(seq))):
+# 				if not (f in subdivision_seq): 
+# 					rhythm_category = 'poly'
+# 					break
+# 			return rhythm_category
 		
-		rhythm_category = get_rhythm_category()
+# 		rhythm_category = get_rhythm_category()
 
-		if model == 'LHL':	
-			import LHL
-			if weight_seq == None:
-				weight_seq = range(0,-L_max,-1)
-			syncopation = LHL.get_syncopation(seq, subdivision_seq, weight_seq, prebar_seq, rhythm_category)
-		elif model == 'PRS':	
-			import PRS
-			syncopation = PRS.get_syncopation(seq, subdivision_seq, postbar_seq, rhythm_category)
-		elif model == 'TMC':	
-			import TMC
-			if weight_seq == None:
-				weight_seq = range(L_max+1,0,-1)
-			syncopation = TMC.get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category)
-		elif model == 'SG':		
-			import SG
-			if weight_seq == None:
-				weight_seq = range(L_max+1)
-			syncopation = SG.get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category)
-		elif model == 'KTH':
-			import KTH
-			syncopation = KTH.get_syncopation(seq, timesig, postbar_seq)
-		elif model == 'TOB':	
-			import TOB
-			syncopation = TOB.get_syncopation(seq)
-		elif model == 'WNBD':
-			import WNBD
-			if strong_beat_level == None:
-				if timesig == '4/4':
-					strong_beat_level = 2
-				else:
-					strong_beat_level = 1 
-			syncopation = WNBD.get_syncopation(seq, subdivision_seq, strong_beat_level, postbar_seq)
+# 		if model == 'LHL':	
+# 			import LHL
+# 			if weight_seq == None:
+# 				weight_seq = range(0,-L_max,-1)
+# 			syncopation = LHL.get_syncopation(seq, subdivision_seq, weight_seq, prebar_seq, rhythm_category)
+# 		elif model == 'PRS':	
+# 			import PRS
+# 			syncopation = PRS.get_syncopation(seq, subdivision_seq, postbar_seq, rhythm_category)
+# 		elif model == 'TMC':	
+# 			import TMC
+# 			if weight_seq == None:
+# 				weight_seq = range(L_max+1,0,-1)
+# 			syncopation = TMC.get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category)
+# 		elif model == 'SG':		
+# 			import SG
+# 			if weight_seq == None:
+# 				weight_seq = range(L_max+1)
+# 			syncopation = SG.get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category)
+# 		elif model == 'KTH':
+# 			import KTH
+# 			syncopation = KTH.get_syncopation(seq, timesig, postbar_seq)
+# 		elif model == 'TOB':	
+# 			import TOB
+# 			syncopation = TOB.get_syncopation(seq)
+# 		elif model == 'WNBD':
+# 			import WNBD
+# 			if strong_beat_level == None:
+# 				if timesig == '4/4':
+# 					strong_beat_level = 2
+# 				else:
+# 					strong_beat_level = 1 
+# 			syncopation = WNBD.get_syncopation(seq, subdivision_seq, strong_beat_level, postbar_seq)
 
-		else:
-			print 'Error: undefined syncopation model.'
+# 		else:
+# 			print 'Error: undefined syncopation model.'
 
-	return syncopation
+# 	return syncopation
 
 # def syncopation_all(rhythm, model, timesig, subdivision_seq = None, weight_seq = None, L_max = 5, strong_beat_level = None):
 # 	syncopation = 0