diff Syncopation models/basic_functions.py @ 1:b2da092dc2e0

The consolidated syncopation software. Have finished individual model and basic functions. Need to revise the coding in main.py, and add rhythm-input interface.
author Chunyang Song <csong@eecs.qmul.ac.uk>
date Sun, 05 Oct 2014 21:52:41 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Syncopation models/basic_functions.py	Sun Oct 05 21:52:41 2014 +0100
@@ -0,0 +1,163 @@
+# This python file is a collection of basic functions that are used in the syncopation models. 
+
+import math
+
+# The concatenation function is used to concatenate two sequences.
+def concatenate(seq1,seq2):
+	return seq1+seq2
+
+# The repetition function is to concatenate a sequence to itself for 'times' number of times.
+def repeat(seq,times):
+	new_seq = list(seq)
+	if times >= 1:
+		for i in range(times-1):
+			new_seq = concatenate(new_seq,seq)
+	else:
+		#print 'Error: repetition times needs to be no less than 1.'
+		new_seq = []
+	return new_seq
+
+# The subdivision function is to equally subdivide a sequence into 'divisor' number of segments.
+def subdivide(seq,divisor):
+	subSeq = []
+	if len(seq) % divisor != 0:
+		print 'Error: rhythmic sequence cannot be equally subdivided.'
+	else:
+		n = len(seq) / divisor
+		start , end = 0, n
+		for i in range(divisor):
+			subSeq.append(seq[start : end])
+			start = end
+			end = end + n	
+	return subSeq
+
+
+# The ceiling function is to round each number inside a sequence up to its nearest integer.
+def ceiling(seq):
+	seq_ceil = []
+	for s in seq:
+		seq_ceil.append(int(math.ceil(s)))
+	return seq_ceil
+
+# The find_divisor function returns a list of all possible divisors for a length of sequence.
+def find_divisor(number):
+	divisors = [1]
+	for i in range(2,number+1):
+		if number%i ==0:
+			divisors.append(i)
+	return divisors
+
+# The find_divisor function returns a list of all possible divisors for a length of sequence.
+def find_prime_factors(number):
+	prime_factors = find_divisor(number)
+	
+	def is_prime(num):
+		if num < 2:
+			return False
+		if num == 2:
+			return True
+		else:
+			for div in range(2,num):
+				if num % div == 0:
+					return False
+		return True
+
+	for i in range(len(prime_factors)-1,0,-1):
+		if is_prime(prime_factors[i]) == False:
+			del prime_factors[i]
+
+	return prime_factors
+
+# The min_timeSpan function searches for the shortest possible time-span representation for a sequence.
+def get_min_timeSpan(seq):
+	min_ts = [1]
+	for d in find_divisor(len(seq)):
+		segments = subdivide(seq,d)
+		if len(segments)!=0:
+			del min_ts[:]
+			for s in segments:
+				min_ts.append(s[0])
+			if sum(min_ts) == sum(seq):
+				break
+	return min_ts
+
+# get_note_indices returns all the indices of all the notes in this sequence
+def get_note_indices(seq):
+	note_indices = []
+
+	for index in range(len(seq)):
+		if seq[index] != 0:
+			note_indices.append(index)
+
+	return note_indices
+
+# The get_H returns a sequence of metrical weight for a certain metrical level (horizontal),
+# given the sequence of metrical weights in a hierarchy (vertical) and a sequence of subdivisions.
+def get_H(weight_seq,subdivision_seq, level):
+	H = []
+	#print len(weight_seq), len(subdivision_seq), level
+	if (level <= len(subdivision_seq)-1) & (level <= len(weight_seq)-1):
+		if level == 0:
+			H = repeat([weight_seq[0]],subdivision_seq[0])
+		else:
+			H_pre = get_H(weight_seq,subdivision_seq,level-1)
+			for h in H_pre:
+				H = concatenate(H, concatenate([h], repeat([weight_seq[level]],subdivision_seq[level]-1)))
+	else:
+		print 'Error: a subdivision factor or metrical weight is not defined for the request metrical level.'
+	return H
+
+# 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):
+	subdivision_seq = []
+
+	if timesig == '2/4' or timesig == '4/4':
+		subdivision_seq = [1,2,2]
+	elif timesig == '3/4':
+		subdivision_seq = [1,3,2]
+	elif timesig == '6/8':
+		subdivision_seq = [1,2,3]
+	elif timesig == '9/8':
+		subdivision_seq = [1,3,3]
+	elif timesig == '12/8':
+		subdivision_seq = [1,4,3]
+	elif timesig == '5/4':
+		subdivision_seq = [1,5,2]
+	elif timesig == '7/4':
+		subdivision_seq = [1,7,2]
+	elif timesig == '11/4':
+		subdivision_seq = [1,11,2]
+	else:
+		print 'Undefined time-signature. Please indicate subdivision sequence for this requested time-signature, e.g. [1,2,2] for 4/4 meter.'
+		for i in range(3):
+			s = int(input('Enter the subdivision factor at metrical level '+str(i)+':'))
+			subdivision_seq.append(s)
+
+	if L_max > 2:
+		subdivision_seq = subdivision_seq + [2]*(L_max-2)
+	else:
+		subdivision_seq = subdivision_seq[0:L_max+1]
+	
+	return subdivision_seq
+
+ # The split_by_bar function seperates the score representation of rhythm by bar lines, 
+ # resulting in a list representingbar-by-bar rhythm sequence,
+ # e.g. rhythm = ['|',[ts1,td1,v1], [ts2,td2,v2], '|',[ts3,td3,v3],'|'...]
+ # rhythm_bybar = [ [ [ts1,td1,v1], [ts2,td2,v2] ], [ [ts3,td3,v3] ], [...]]
+# def split_by_bar(rhythm):
+# 	rhythm_bybar = []
+# 	bar_index = []
+# 	for index in range(len(rhythm)):
+# 		if rhythm[index] == '|':
+
+# 	return rhythm_bybar
+
+# def yseq_to_vseq(yseq):
+# 	vseq = []
+
+# 	return vseq
+
+
+# # testing
+# print find_prime_factors(10)
\ No newline at end of file