christopher@45
|
1 '''
|
christopher@45
|
2 Author: Chunyang Song
|
christopher@45
|
3 Institution: Centre for Digital Music, Queen Mary University of London
|
christopher@45
|
4
|
christopher@45
|
5 '''
|
christopher@45
|
6
|
christopher@45
|
7 from basic_functions import get_note_indices, repeat, velocity_sequence_to_min_timespan
|
christopher@45
|
8
|
christopher@45
|
9 # To find the nearest power of 2 equal to or less than the given number
|
christopher@45
|
10 def round_down_power_2(number):
|
christopher@45
|
11 i = 0
|
christopher@45
|
12 if number > 0:
|
christopher@45
|
13 while pow(2,i) > number or number >= pow(2,i+1):
|
christopher@45
|
14 i = i+1
|
christopher@45
|
15 power2 = pow(2,i)
|
christopher@45
|
16 else:
|
christopher@45
|
17 print 'Error: numbers that are less than 1 cannot be rounded down to its nearest power of two.'
|
christopher@45
|
18 power2 = None
|
christopher@45
|
19 return power2
|
christopher@45
|
20
|
christopher@45
|
21 # To find the nearest power of 2 equal to or more than the given number
|
christopher@45
|
22 def round_up_power_2(number):
|
christopher@45
|
23 i = 0
|
christopher@45
|
24 while pow(2,i) < number:
|
christopher@45
|
25 i = i + 1
|
christopher@45
|
26 return pow(2,i)
|
christopher@45
|
27
|
christopher@45
|
28 # To examine whether start_time is 'off-beat'
|
christopher@45
|
29 def start_time_offbeat_measure(startTime, c_n):
|
christopher@45
|
30 measure = 0
|
christopher@45
|
31 if startTime % c_n != 0:
|
christopher@45
|
32 measure = 2
|
christopher@45
|
33 return measure
|
christopher@45
|
34
|
christopher@45
|
35 # To examine whether end_time is 'off-beat'
|
christopher@45
|
36 def end_time_offbeat_measure(endTime, c_n):
|
christopher@45
|
37 measure = 0
|
christopher@45
|
38 if endTime % c_n != 0:
|
christopher@45
|
39 measure = 1
|
christopher@45
|
40 return measure
|
christopher@45
|
41
|
christopher@45
|
42 def get_syncopation(bar, parameters = None):
|
christopher@45
|
43 syncopation = None
|
christopher@45
|
44
|
christopher@45
|
45 # KTH only deals with simple-duple meter where the number of beats per bar is a power of two.
|
christopher@45
|
46 numerator = bar.get_time_signature().get_numerator()
|
christopher@45
|
47 if numerator != round_down_power_2(numerator):
|
christopher@45
|
48 print 'Warning: KTH model detects non simple-duple meter so returning None.'
|
christopher@45
|
49 else:
|
christopher@45
|
50 # retrieve note-sequence and next bar's note-sequence
|
christopher@45
|
51 noteSequence = bar.get_note_sequence()
|
christopher@45
|
52 #for note in noteSequence:
|
christopher@45
|
53 # print note.to_string()
|
christopher@45
|
54 #print 'barlength',bar.get_bar_ticks()
|
christopher@45
|
55
|
christopher@45
|
56 nextbarNoteSequence = None
|
christopher@45
|
57 if bar.get_next_bar() != None:
|
christopher@45
|
58 nextbarNoteSequence = bar.get_next_bar().get_note_sequence()
|
christopher@45
|
59
|
christopher@45
|
60 # convert note sequence to its minimum time-span representation so that the later calculation can be faster
|
christopher@45
|
61 # noteSequence = note_sequence_to_min_timespan(noteSequence)
|
christopher@45
|
62 # find delta_t
|
christopher@45
|
63 Tmin = len(velocity_sequence_to_min_timespan(bar.get_velocity_sequence()))
|
christopher@45
|
64 #print 'Tmin',Tmin
|
christopher@45
|
65 T = round_up_power_2(Tmin)
|
christopher@45
|
66 #print 'T',T
|
christopher@45
|
67 deltaT = float(bar.get_bar_ticks())/T
|
christopher@45
|
68 #print 'delta',deltaT
|
christopher@45
|
69
|
christopher@45
|
70
|
christopher@45
|
71 # calculate syncopation note by note
|
christopher@45
|
72 syncopation = 0
|
christopher@45
|
73
|
christopher@45
|
74 for note in noteSequence:
|
christopher@45
|
75 c_n = round_down_power_2(note.duration/deltaT)
|
christopher@45
|
76 #print 'd', note.duration
|
christopher@45
|
77 #print 'c_n', c_n
|
christopher@45
|
78 endTime = note.startTime + note.duration
|
christopher@45
|
79 #print float(note.startTime)/deltaT, float(endTime)/deltaT
|
christopher@45
|
80 syncopation = syncopation + start_time_offbeat_measure(float(note.startTime)/deltaT,c_n) + end_time_offbeat_measure(float(endTime)/deltaT,c_n)
|
christopher@45
|
81
|
christopher@45
|
82
|
christopher@45
|
83 return syncopation
|
christopher@45
|
84
|
christopher@45
|
85 # # To calculate syncopation value of the sequence in the given time-signature.
|
christopher@45
|
86 # def get_syncopation(seq, timesig, postbar_seq):
|
christopher@45
|
87 # syncopation = 0
|
christopher@45
|
88
|
christopher@45
|
89 # numerator = int(timesig.split("/")[0])
|
christopher@45
|
90 # if numerator == round_down_power_2(numerator): # if is a binary time-signature
|
christopher@45
|
91 # # converting to minimum time-span format
|
christopher@45
|
92 # seq = get_min_timeSpan(seq)
|
christopher@45
|
93 # if postbar_seq != None:
|
christopher@45
|
94 # postbar_seq = get_min_timeSpan(postbar_seq)
|
christopher@45
|
95
|
christopher@45
|
96 # # sf is a stretching factor matching rhythm sequence and meter, as Keith defines the note duration as a multiple of 1/(2^d) beats where d is number of metrical level
|
christopher@45
|
97 # sf = round_up_power_2(len(seq))
|
christopher@45
|
98
|
christopher@45
|
99 # # retrieve all the indices of all the notes in this sequence
|
christopher@45
|
100 # note_indices = get_note_indices(seq)
|
christopher@45
|
101
|
christopher@45
|
102 # for i in range(len(note_indices)):
|
christopher@45
|
103 # # Assuming start_time is the index of this note, end_time is the index of the following note
|
christopher@45
|
104 # start_time = note_indices[i]*sf/float(len(seq))
|
christopher@45
|
105
|
christopher@45
|
106 # if i == len(note_indices)-1: # if this is the last note, end_time is the index of the following note in the next bar
|
christopher@45
|
107 # if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)):
|
christopher@45
|
108 # next_index = get_note_indices(postbar_seq)[0]+len(seq)
|
christopher@45
|
109 # end_time = next_index*sf/float(len(seq))
|
christopher@45
|
110 # else: # or if the next bar is none or full rest, end_time is the end of this sequence.
|
christopher@45
|
111 # end_time = sf
|
christopher@45
|
112 # else:
|
christopher@45
|
113 # end_time = note_indices[i+1]*sf/float(len(seq))
|
christopher@45
|
114
|
christopher@45
|
115 # duration = end_time - start_time
|
christopher@45
|
116 # c_n = round_down_power_2(duration)
|
christopher@45
|
117 # syncopation = syncopation + start(start_time,c_n) + end(end_time,c_n)
|
christopher@45
|
118 # else:
|
christopher@45
|
119 # print 'Error: KTH model can only deal with binary time-signature, e.g. 2/4 and 4/4. '
|
christopher@45
|
120 # syncopation = None
|
christopher@45
|
121
|
christopher@45
|
122 # return syncopation
|