comparison Syncopation models/synpy/PRS.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 e71028851131
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 from basic_functions import repeat, subdivide, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category
7
8 def get_cost(sequence,nextSequence):
9 sequence = velocity_sequence_to_min_timespan(sequence) # converting to the minimum time-span format
10
11 if sequence[1:] == repeat([0],len(sequence)-1): # null prototype
12 cost = 0
13 elif sequence == repeat([1],len(sequence)): # filled prototype
14 cost = 1
15 elif sequence[0] == 1 and sequence[-1] == 0: # run1 prototype
16 cost = 2
17 elif sequence[0] == 1 and (nextSequence == None or nextSequence[0] == 0): # run2 prototype
18 cost = 2
19 elif sequence[-1] == 1 and nextSequence != None and nextSequence[0] == 1: # upbeat prototype
20 cost = 3
21 elif sequence[0] == 0: # syncopated prototype
22 cost = 5
23
24 return cost
25
26 # This function calculates the syncopation value (cost) for the sequence with the postbar_seq for a certain level.
27 def syncopation_perlevel(subSequences):
28 #print 'subSequences', subSequences
29 total = 0
30 for l in range(len(subSequences)-1):
31 #print 'cost', get_cost(subSequences[l], subSequences[l+1])
32 total = total + get_cost(subSequences[l], subSequences[l+1])
33 #print 'total this level', total
34 normalised = float(total)/(len(subSequences)-1)
35
36 return normalised
37
38 def get_syncopation(bar, parameters = None):
39 syncopation = None
40
41 binarySequence = bar.get_binary_sequence()
42 subdivisionSequence = bar.get_subdivision_sequence()
43
44 # PRS does not handle polyrhythms
45 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
46 print 'Warning: PRS model detects polyrhythms so returning None.'
47 else:
48 syncopation = 0
49
50 # retrieve the binary sequence in the next bar
51 if bar.get_next_bar() != None:
52 nextbarBinarySequence = bar.get_next_bar().get_binary_sequence()
53 else:
54 nextbarBinarySequence = None
55
56 # numberOfSubSeqs is the number of sub-sequences at a certain metrical level, initialised to be 1 (at the bar level)
57 numberOfSubSeqs = 1
58 for subdivisor in subdivisionSequence:
59 # numberOfSubSeqs is product of all the subdivisors up to the current level
60 numberOfSubSeqs = numberOfSubSeqs * subdivisor
61
62 # recursion stops when the length of sub-sequence is less than 2
63 if len(binarySequence)/numberOfSubSeqs >= 2:
64 # generate sub-sequences and append the next bar sequence
65 subSequences = subdivide(ceiling(binarySequence), numberOfSubSeqs)
66 subSequences.append(nextbarBinarySequence)
67 # adding syncopation at each metrical level to the total syncopation
68 #print 'per level', syncopation_perlevel(subSequences)
69 syncopation += syncopation_perlevel(subSequences)
70 else:
71 break
72
73 return syncopation