annotate 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
rev   line source
christopher@45 1 '''
christopher@45 2 Author: Chunyang Song
christopher@45 3 Institution: Centre for Digital Music, Queen Mary University of London
christopher@45 4
christopher@45 5 '''
christopher@45 6
christopher@45 7 from basic_functions import get_H, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category
christopher@45 8 from parameter_setter import are_parameters_valid
christopher@45 9
christopher@45 10 # The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level.
christopher@45 11 def get_metricity(binarySequence, H):
christopher@45 12 metricity = 0
christopher@45 13 for m in range(len(binarySequence)):
christopher@45 14 metricity = metricity + binarySequence[m]*H[m]
christopher@45 15 return metricity
christopher@45 16
christopher@45 17 # The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence.
christopher@45 18 def get_max_metricity(binarySequence, H):
christopher@45 19 maxMetricity = 0
christopher@45 20 H.sort(reverse=True) # Sort the metrical weight sequence from large to small
christopher@45 21 for i in range(sum(binarySequence)):
christopher@45 22 maxMetricity = maxMetricity+H[i]
christopher@45 23 return maxMetricity
christopher@45 24
christopher@45 25 # find the metrical level L that contains the same number of metrical positions as the length of the binary sequence
christopher@45 26 # if the given Lmax is not big enough to analyse the given sequence, request a bigger Lmax
christopher@45 27 def find_L(rhythmSequence, Lmax, weightSequence, subdivisionSequence):
christopher@45 28 L = Lmax
christopher@45 29
christopher@45 30 # initially assuming the Lmax is not big enough
christopher@45 31 needBiggerLmax = True
christopher@45 32
christopher@45 33 # from the lowest metrical level (Lmax) to the highest, find the matching metrical level that
christopher@45 34 # has the same length as the length of binary sequence
christopher@45 35 while L >= 0:
christopher@45 36 if len(get_H(weightSequence,subdivisionSequence, L)) == len(rhythmSequence):
christopher@45 37 needBiggerLmax = False
christopher@45 38 break
christopher@45 39 else:
christopher@45 40 L = L - 1
christopher@45 41
christopher@45 42 # if need a bigger Lmax, print error message and return None; otherwise return the matching metrical level L
christopher@45 43 if needBiggerLmax:
christopher@45 44 print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
christopher@45 45 L = None
christopher@45 46
christopher@45 47 return L
christopher@45 48
christopher@45 49 # The get_syncopation function calculates the syncopation value of the given sequence for TMC model.
christopher@45 50 #def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
christopher@45 51 def get_syncopation(bar, parameters = None):
christopher@45 52 syncopation = None
christopher@45 53 binarySequence = bar.get_binary_sequence()
christopher@45 54 subdivisionSequence = bar.get_subdivision_sequence()
christopher@45 55
christopher@45 56 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
christopher@45 57 print 'Warning: TMC model detects polyrhythms so returning None.'
christopher@45 58 else:
christopher@45 59
christopher@45 60 # set the defaults
christopher@45 61 Lmax = 5
christopher@45 62 weightSequence = range(Lmax+1,0,-1) # i.e. [6,5,4,3,2,1]
christopher@45 63
christopher@45 64 if parameters!= None:
christopher@45 65 if 'Lmax' in parameters:
christopher@45 66 Lmax = parameters['Lmax']
christopher@45 67 if 'W' in parameters:
christopher@45 68 weightSequence = parameters['W']
christopher@45 69
christopher@45 70 if not are_parameters_valid(Lmax, weightSequence, subdivisionSequence):
christopher@45 71 print 'Error: the given parameters are not valid.'
christopher@45 72 else:
christopher@45 73 binarySequence = velocity_sequence_to_min_timespan(binarySequence) # converting to the minimum time-span format
christopher@45 74 L = find_L(binarySequence, Lmax, weightSequence, subdivisionSequence)
christopher@45 75 if L != None:
christopher@45 76 #? generate the metrical weights of the lowest level,
christopher@45 77 #? using the last matching_level number of elements in the weightSequence, to make sure the last element is 1
christopher@45 78 H = get_H (weightSequence[-(L+1):], subdivisionSequence, L)
christopher@45 79 metricity = get_metricity(binarySequence, H) # converting to binary sequence then calculate metricity
christopher@45 80 maxMetricity = get_max_metricity(binarySequence, H)
christopher@45 81
christopher@45 82 syncopation = maxMetricity - metricity
christopher@45 83
christopher@45 84 return syncopation
christopher@45 85