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
|