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@1
|
7 from basic_functions import get_H, ceiling, get_min_timeSpan
|
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@1
|
10 def get_metricity(seq, H):
|
csong@1
|
11 metricity = 0
|
csong@1
|
12 for m in range(len(seq)):
|
csong@1
|
13 metricity = metricity + seq[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@1
|
17 def get_max_metricity(seq, H):
|
csong@1
|
18 max_metricity = 0
|
csong@1
|
19 H.sort(reverse=True) # Sort the metrical weight sequence from large to small
|
csong@1
|
20 for i in range(sum(seq)):
|
csong@1
|
21 max_metricity = max_metricity+H[i]
|
csong@1
|
22 return max_metricity
|
csong@1
|
23
|
csong@1
|
24 # The get_syncopation function calculates the syncopation value of the given sequence for TMC model.
|
csong@1
|
25 def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
|
csong@1
|
26 syncopation = None
|
csong@1
|
27 if rhythm_category == 'poly':
|
csong@1
|
28 print 'Error: TMC model cannot deal with polyrhythms.'
|
csong@1
|
29 else:
|
csong@1
|
30 seq = get_min_timeSpan(seq) # converting to the minimum time-span format
|
csong@1
|
31
|
csong@1
|
32 # checking whether the given L_max is enough to analyse the given sequence, if not, request a bigger L_max
|
csong@1
|
33 new_L_max = True
|
csong@1
|
34 matching_level = L_max
|
csong@1
|
35 while matching_level >= 0:
|
csong@1
|
36 if len(get_H(weight_seq,subdivision_seq, matching_level)) == len(seq):
|
csong@1
|
37 new_L_max = False
|
csong@1
|
38 break
|
csong@1
|
39 else:
|
csong@1
|
40 matching_level = matching_level - 1
|
csong@1
|
41
|
csong@1
|
42 if new_L_max == True:
|
csong@1
|
43 print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
|
csong@0
|
44
|
csong@0
|
45 else:
|
csong@1
|
46 # generate the metrical weights of the lowest level,
|
csong@1
|
47 # using the last matching_level number of elements in the weight_seq list, to make sure the last element is 1
|
csong@1
|
48 H = get_H (weight_seq[-(matching_level+1):], subdivision_seq, matching_level)
|
csong@0
|
49
|
csong@1
|
50 metricity = get_metricity(ceiling(seq), H) # converting to binary sequence then calculate metricity
|
csong@1
|
51 max_metricity = get_max_metricity(ceiling(seq), H)
|
csong@0
|
52
|
csong@1
|
53 syncopation = max_metricity - metricity
|
csong@1
|
54 return syncopation
|
csong@0
|
55
|