Mercurial > hg > syncopation-dataset
comparison Syncopation models/synpy/SG.py @ 45:6e9154fc58df
moving the code files to the synpy package directory
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Thu, 23 Apr 2015 23:52:04 +0100 |
parents | |
children | 9a60ca4ae0fb |
comparison
equal
deleted
inserted
replaced
44:144460f34b5e | 45:6e9154fc58df |
---|---|
1 ''' | |
2 Author: Chunyang Song | |
3 Institution: Centre for Digital Music, Queen Mary University of London | |
4 | |
5 ''' | |
6 | |
7 from basic_functions import get_H, velocity_sequence_to_min_timespan, get_rhythm_category, upsample_velocity_sequence | |
8 from parameter_setter import are_parameters_valid | |
9 | |
10 def get_syncopation(bar, parameters = None): | |
11 syncopation = None | |
12 velocitySequence = bar.get_velocity_sequence() | |
13 subdivisionSequence = bar.get_subdivision_sequence() | |
14 | |
15 if get_rhythm_category(velocitySequence, subdivisionSequence) == 'poly': | |
16 print 'Warning: SG model detects polyrhythms so returning None.' | |
17 else: | |
18 #velocitySequence = velocity_sequence_to_min_timespan(velocitySequence) # converting to the minimum time-span format | |
19 | |
20 # set the defaults | |
21 Lmax = 5 | |
22 weightSequence = range(Lmax+1) # i.e. [0,1,2,3,4,5] | |
23 if parameters!= None: | |
24 if 'Lmax' in parameters: | |
25 Lmax = parameters['Lmax'] | |
26 if 'W' in parameters: | |
27 weightSequence = parameters['W'] | |
28 | |
29 if not are_parameters_valid(Lmax, weightSequence, subdivisionSequence): | |
30 print 'Error: the given parameters are not valid.' | |
31 else: | |
32 # generate the metrical weights of level Lmax, and upsample(stretch) the velocity sequence to match the length of H | |
33 H = get_H(weightSequence,subdivisionSequence, Lmax) | |
34 | |
35 velocitySequence = upsample_velocity_sequence(velocitySequence, len(H)) | |
36 | |
37 # The ave_dif_neighbours function calculates the (weighted) average of the difference between the note at a certain index and its neighbours in a certain metrical level | |
38 def ave_dif_neighbours(index, level): | |
39 | |
40 averages = [] | |
41 parameterGarma = 0.8 | |
42 | |
43 # The findPre function is to calculate the index of the previous neighbour at a certain metrical level. | |
44 def find_pre(index, level): | |
45 preIndex = (index - 1)%len(H) # using % is to restrict the index varies within range(0, len(H)) | |
46 while(H[preIndex] > level): | |
47 preIndex = (preIndex - 1)%len(H) | |
48 #print 'preIndex', preIndex | |
49 return preIndex | |
50 | |
51 # The findPost function is to calculate the index of the next neighbour at a certain metrical level. | |
52 def find_post(index, level): | |
53 postIndex = (index + 1)%len(H) | |
54 while(H[postIndex] > level): | |
55 postIndex = (postIndex + 1)%len(H) | |
56 #print 'postIndex', postIndex | |
57 return postIndex | |
58 | |
59 # The dif function is to calculate a difference level factor between two notes (at note position index1 and index 2) in velocity sequence | |
60 def dif(index1,index2): | |
61 parameterBeta = 0.5 | |
62 dif_v = velocitySequence[index1]-velocitySequence[index2] | |
63 dif_h = abs(H[index1]-H[index2]) | |
64 dif = dif_v*(parameterBeta*dif_h/4+1-parameterBeta) | |
65 #print 'dif', dif | |
66 return dif | |
67 | |
68 # From the highest to the lowest metrical levels where the current note resides, calculate the difference between the note and its neighbours at that level | |
69 for l in range(level, max(H)+1): | |
70 ave = (parameterGarma*dif(index,find_pre(index,l))+dif(index,find_post(index,l)) )/(1+parameterGarma) | |
71 averages.append(ave) | |
72 #print 'averages', averages | |
73 return averages | |
74 | |
75 # if the upsampling was successfully done | |
76 if velocitySequence != None: | |
77 syncopation = 0 | |
78 # Calculate the syncopation value for each note | |
79 for index in range(len(velocitySequence)): | |
80 if velocitySequence[index] != 0: # Onset detected | |
81 h = H[index] | |
82 # Syncopation potential according to its metrical level, which is equal to the metrical weight | |
83 potential = 1 - pow(0.5,h) | |
84 level = h # Metrical weight is equal to its metrical level | |
85 syncopation += min(ave_dif_neighbours(index, level))*potential | |
86 else: | |
87 print 'Try giving a bigger Lmax so that the rhythm sequence can be measured by the matching metrical weights sequence (H).' | |
88 return syncopation |