view Syncopation models/KTH.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 031e2ccb1fb6
line wrap: on
line source
'''
Author: Chunyang Song
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

# To find the nearest power of 2 equal to or less than the given number
def roundDownPower2(number):
	i = 0
	if number > 0:
		while pow(2,i) > number or number >= pow(2,i+1):
			i = i+1
		power2 = pow(2,i)
	else:
		print 'Error: numbers that are less than 1 cannot be rounded down to its nearest power of two.'
		power2 = None
	return power2

# To find the nearest power of 2 equal to or more than the given number
def roundUpPower2(number):
	i = 0
	while pow(2,i) < number:
		i = i + 1
	return pow(2,i)

# To examine whether start_time is 'off-beat'
def start(start_time, c_n):
	s = 0
	if start_time % c_n != 0:
		s = 2
	return s

# To examine whether end_time is 'off-beat'
def end(end_time, c_n):
	s = 0
	if end_time % c_n != 0:
		s = 1
	return s

# 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 == roundDownPower2(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 = roundUpPower2(len(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))

			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 = roundDownPower2(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