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@1
|
6 from basic_functions import repeat, subdivide, ceiling, get_min_timeSpan
|
csong@1
|
7
|
csong@1
|
8 def get_cost(seq,next_seq):
|
csong@1
|
9 seq = get_min_timeSpan(seq) # converting to the minimum time-span format
|
csong@1
|
10
|
csong@1
|
11 if seq[1:] == repeat([0],len(seq)-1): # null prototype
|
csong@1
|
12 cost = 0
|
csong@1
|
13 elif seq == repeat([1],len(seq)): # filled prototype
|
csong@1
|
14 cost = 1
|
csong@1
|
15 elif seq[0] == 1 and seq[-1] == 0: # run1 prototype
|
csong@1
|
16 cost = 2
|
csong@1
|
17 elif seq[0] == 1 and (next_seq == None or next_seq[0] == 0): # run2 prototype
|
csong@1
|
18 cost = 2
|
csong@1
|
19 elif seq[0] == 1 and seq[-1] == 1 and next_seq != None and next_seq[0] == 1: # upbeat prototype
|
csong@1
|
20 cost = 3
|
csong@1
|
21 elif seq[0] == 0: # syncopated prototype
|
csong@1
|
22 cost = 5
|
csong@1
|
23
|
csong@1
|
24 return cost
|
csong@1
|
25
|
csong@1
|
26 # This function calculates the syncopation value (cost) for the sequence with the postbar_seq for a certain level.
|
csong@1
|
27 def syncopation_perlevel(sub_seqs, num_subs):
|
csong@1
|
28 total = 0
|
csong@1
|
29 for l in range(num_subs):
|
csong@1
|
30 total = total + get_cost(sub_seqs[l], sub_seqs[l+1])
|
csong@1
|
31 normalised = float(total)/num_subs
|
csong@1
|
32
|
csong@1
|
33 return normalised
|
csong@1
|
34
|
csong@1
|
35 # This function calculates the overall syncopation value for a bar of sequence..
|
csong@1
|
36 def get_syncopation(seq,subdivision_seq, postbar_seq, rhythm_category):
|
csong@1
|
37 syncopation = None
|
csong@1
|
38 if rhythm_category == 'poly':
|
csong@1
|
39 print 'Error: PRS model cannot deal with polyrhythms.'
|
csong@0
|
40 else:
|
csong@1
|
41 syncopation = 0
|
csong@0
|
42
|
csong@1
|
43 current_num_subs = 1 # the initial number of sub-sequences at a certain metrical level
|
csong@1
|
44 for subdivisor in subdivision_seq:
|
csong@1
|
45 # the number of sub-sequence at the current level is product of all the subdivisors up to the current level
|
csong@1
|
46 current_num_subs = current_num_subs * subdivisor
|
csong@1
|
47 # recursion stops when the length of sub-sequence is less than 2
|
csong@1
|
48 if len(seq)/current_num_subs >= 2:
|
csong@1
|
49 # generate sub-sequences and append the next bar sequence
|
csong@1
|
50 sub_seqs = subdivide(ceiling(seq), current_num_subs)
|
csong@1
|
51 sub_seqs.append(postbar_seq)
|
csong@1
|
52 # adding syncopation at each metrical level to the total syncopation
|
csong@1
|
53 syncopation += syncopation_perlevel(sub_seqs, current_num_subs)
|
csong@1
|
54 else:
|
csong@1
|
55 break
|
csong@0
|
56
|
csong@1
|
57 return syncopation
|