Mercurial > hg > syncopation-dataset
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 |