csong@0: ''' csong@0: Author: Chunyang Song csong@0: Institution: Centre for Digital Music, Queen Mary University of London csong@0: csong@0: ''' csong@0: csong@1: from basic_functions import get_H, ceiling, get_min_timeSpan csong@0: csong@1: # The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level. csong@1: def get_metricity(seq, H): csong@1: metricity = 0 csong@1: for m in range(len(seq)): csong@1: metricity = metricity + seq[m]*H[m] csong@1: return metricity csong@1: csong@1: # The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence. csong@1: def get_max_metricity(seq, H): csong@1: max_metricity = 0 csong@1: H.sort(reverse=True) # Sort the metrical weight sequence from large to small csong@1: for i in range(sum(seq)): csong@1: max_metricity = max_metricity+H[i] csong@1: return max_metricity csong@1: csong@1: # The get_syncopation function calculates the syncopation value of the given sequence for TMC model. csong@1: def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): csong@1: syncopation = None csong@1: if rhythm_category == 'poly': csong@1: print 'Error: TMC model cannot deal with polyrhythms.' csong@1: else: csong@1: seq = get_min_timeSpan(seq) # converting to the minimum time-span format csong@1: csong@1: # checking whether the given L_max is enough to analyse the given sequence, if not, request a bigger L_max csong@1: new_L_max = True csong@1: matching_level = L_max csong@1: while matching_level >= 0: csong@1: if len(get_H(weight_seq,subdivision_seq, matching_level)) == len(seq): csong@1: new_L_max = False csong@1: break csong@1: else: csong@1: matching_level = matching_level - 1 csong@1: csong@1: if new_L_max == True: csong@1: print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.' csong@0: csong@0: else: csong@1: # generate the metrical weights of the lowest level, csong@1: # using the last matching_level number of elements in the weight_seq list, to make sure the last element is 1 csong@1: H = get_H (weight_seq[-(matching_level+1):], subdivision_seq, matching_level) csong@0: csong@1: metricity = get_metricity(ceiling(seq), H) # converting to binary sequence then calculate metricity csong@1: max_metricity = get_max_metricity(ceiling(seq), H) csong@0: csong@1: syncopation = max_metricity - metricity csong@1: return syncopation csong@0: