annotate Syncopation models/TMC.py @ 23:df1e7c378ee0

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