christopher@45: ''' christopher@45: Author: Chunyang Song christopher@45: Institution: Centre for Digital Music, Queen Mary University of London christopher@45: christopher@45: ''' christopher@45: christopher@71: from basic_functions import get_H, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category, find_rhythm_Lmax christopher@45: from parameter_setter import are_parameters_valid christopher@45: christopher@45: # The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level. christopher@45: def get_metricity(binarySequence, H): christopher@45: metricity = 0 christopher@45: for m in range(len(binarySequence)): christopher@45: metricity = metricity + binarySequence[m]*H[m] christopher@45: return metricity christopher@45: christopher@45: # The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence. christopher@45: def get_max_metricity(binarySequence, H): christopher@45: maxMetricity = 0 christopher@45: H.sort(reverse=True) # Sort the metrical weight sequence from large to small christopher@45: for i in range(sum(binarySequence)): christopher@45: maxMetricity = maxMetricity+H[i] christopher@45: return maxMetricity christopher@45: christopher@45: christopher@45: christopher@45: # The get_syncopation function calculates the syncopation value of the given sequence for TMC model. christopher@45: #def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): christopher@45: def get_syncopation(bar, parameters = None): christopher@45: syncopation = None christopher@45: binarySequence = bar.get_binary_sequence() christopher@45: subdivisionSequence = bar.get_subdivision_sequence() christopher@45: christopher@45: if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly': christopher@45: print 'Warning: TMC model detects polyrhythms so returning None.' christopher@45: else: christopher@45: christopher@45: # set the defaults christopher@45: Lmax = 5 christopher@45: weightSequence = range(Lmax+1,0,-1) # i.e. [6,5,4,3,2,1] christopher@45: christopher@45: if parameters!= None: christopher@45: if 'Lmax' in parameters: christopher@45: Lmax = parameters['Lmax'] christopher@45: if 'W' in parameters: christopher@45: weightSequence = parameters['W'] christopher@45: christopher@45: if not are_parameters_valid(Lmax, weightSequence, subdivisionSequence): christopher@45: print 'Error: the given parameters are not valid.' christopher@45: else: christopher@45: binarySequence = velocity_sequence_to_min_timespan(binarySequence) # converting to the minimum time-span format christopher@71: L = find_rhythm_Lmax(binarySequence, Lmax, weightSequence, subdivisionSequence) christopher@45: if L != None: christopher@45: #? generate the metrical weights of the lowest level, christopher@45: #? using the last matching_level number of elements in the weightSequence, to make sure the last element is 1 christopher@45: H = get_H (weightSequence[-(L+1):], subdivisionSequence, L) christopher@45: metricity = get_metricity(binarySequence, H) # converting to binary sequence then calculate metricity christopher@45: maxMetricity = get_max_metricity(binarySequence, H) christopher@45: christopher@45: syncopation = maxMetricity - metricity christopher@45: christopher@45: return syncopation christopher@45: