csong@1
|
1 '''
|
csong@1
|
2 Author: Chunyang Song
|
csong@1
|
3 Institution: Centre for Digital Music, Queen Mary University of London
|
csong@1
|
4
|
csong@1
|
5 '''
|
csong@1
|
6 ## Problems! Note indices, post bar
|
csong@1
|
7
|
csong@20
|
8 from basic_functions import get_min_timeSpan, get_note_indices, repeat
|
csong@1
|
9
|
csong@1
|
10 # To find the nearest power of 2 equal to or less than the given number
|
csong@20
|
11 def round_down_power_2(number):
|
csong@1
|
12 i = 0
|
csong@1
|
13 if number > 0:
|
csong@1
|
14 while pow(2,i) > number or number >= pow(2,i+1):
|
csong@1
|
15 i = i+1
|
csong@1
|
16 power2 = pow(2,i)
|
csong@1
|
17 else:
|
csong@1
|
18 print 'Error: numbers that are less than 1 cannot be rounded down to its nearest power of two.'
|
csong@1
|
19 power2 = None
|
csong@1
|
20 return power2
|
csong@1
|
21
|
csong@1
|
22 # To find the nearest power of 2 equal to or more than the given number
|
csong@20
|
23 def round_up_power_2(number):
|
csong@1
|
24 i = 0
|
csong@1
|
25 while pow(2,i) < number:
|
csong@1
|
26 i = i + 1
|
csong@1
|
27 return pow(2,i)
|
csong@1
|
28
|
csong@1
|
29 # To examine whether start_time is 'off-beat'
|
csong@20
|
30 def start(startTime, c_n):
|
csong@1
|
31 s = 0
|
csong@20
|
32 if startTime % c_n != 0:
|
csong@1
|
33 s = 2
|
csong@1
|
34 return s
|
csong@1
|
35
|
csong@1
|
36 # To examine whether end_time is 'off-beat'
|
csong@20
|
37 def end(endTime, c_n):
|
csong@1
|
38 s = 0
|
csong@20
|
39 if endTime % c_n != 0:
|
csong@1
|
40 s = 1
|
csong@1
|
41 return s
|
csong@1
|
42
|
csong@1
|
43 # To calculate syncopation value of the sequence in the given time-signature.
|
csong@20
|
44 #def get_syncopation(seq, timesig, postbar_seq):
|
csong@20
|
45 def get_syncopation(bar, parameter = None):
|
csong@1
|
46 syncopation = 0
|
csong@1
|
47
|
csong@1
|
48 numerator = int(timesig.split("/")[0])
|
csong@20
|
49 if numerator == round_down_power_2(numerator): # if is a binary time-signature
|
csong@1
|
50 # converting to minimum time-span format
|
csong@1
|
51 seq = get_min_timeSpan(seq)
|
csong@1
|
52 if postbar_seq != None:
|
csong@1
|
53 postbar_seq = get_min_timeSpan(postbar_seq)
|
csong@1
|
54
|
csong@1
|
55 # 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
|
csong@20
|
56 sf = round_up_power_2(len(seq))
|
csong@1
|
57
|
csong@1
|
58 # retrieve all the indices of all the notes in this sequence
|
csong@1
|
59 note_indices = get_note_indices(seq)
|
csong@1
|
60
|
csong@1
|
61 for i in range(len(note_indices)):
|
csong@1
|
62 # Assuming start_time is the index of this note, end_time is the index of the following note
|
csong@1
|
63 start_time = note_indices[i]*sf/float(len(seq))
|
csong@1
|
64
|
csong@1
|
65 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
|
csong@1
|
66 if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)):
|
csong@1
|
67 next_index = get_note_indices(postbar_seq)[0]+len(seq)
|
csong@1
|
68 end_time = next_index*sf/float(len(seq))
|
csong@1
|
69 else: # or if the next bar is none or full rest, end_time is the end of this sequence.
|
csong@1
|
70 end_time = sf
|
csong@1
|
71 else:
|
csong@1
|
72 end_time = note_indices[i+1]*sf/float(len(seq))
|
csong@1
|
73
|
csong@1
|
74 duration = end_time - start_time
|
csong@20
|
75 c_n = round_down_power_2(duration)
|
csong@1
|
76 syncopation = syncopation + start(start_time,c_n) + end(end_time,c_n)
|
csong@1
|
77 else:
|
csong@1
|
78 print 'Error: KTH model can only deal with binary time-signature, e.g. 2/4 and 4/4. '
|
csong@1
|
79 syncopation = None
|
csong@1
|
80
|
csong@1
|
81 return syncopation
|