annotate Syncopation models/TMC.py @ 33:f5abd2e8cafe

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