comparison Syncopation models/LHL.py @ 28:5de1cb45c145

Parameters setting implemented.
author csong <csong@eecs.qmul.ac.uk>
date Sun, 12 Apr 2015 22:34:35 +0100
parents b959c2acb927
children f5abd2e8cafe
comparison
equal deleted inserted replaced
27:ed29ed80635c 28:5de1cb45c145
2 Author: Chunyang Song 2 Author: Chunyang Song
3 Institution: Centre for Digital Music, Queen Mary University of London 3 Institution: Centre for Digital Music, Queen Mary University of London
4 ''' 4 '''
5 5
6 from basic_functions import concatenate, repeat, subdivide, ceiling, get_rhythm_category 6 from basic_functions import concatenate, repeat, subdivide, ceiling, get_rhythm_category
7 from parameter_setter import are_parameters_valid
7 8
8 terminalNodes = [] # Global variable, storing all the terminal nodes from recursive tree structure in time order 9 terminalNodes = [] # Global variable, storing all the terminal nodes from recursive tree structure in time order
9 10
10 # Each terminnal node contains two properties: its node type (note or rest) and its metrical weight. 11 # Each terminnal node contains two properties: its node type (note or rest) and its metrical weight.
11 class Node: 12 class Node:
28 subBinarySequences = subdivide(binarySequence, subdivisionSequence[level+1]) 29 subBinarySequences = subdivide(binarySequence, subdivisionSequence[level+1])
29 subWeightSequences = concatenate([metricalWeight],repeat([weightSequence[level+1]],subdivisionSequence[level+1]-1)) 30 subWeightSequences = concatenate([metricalWeight],repeat([weightSequence[level+1]],subdivisionSequence[level+1]-1))
30 for a in range(len(subBinarySequences)): 31 for a in range(len(subBinarySequences)):
31 recursive_tree(subBinarySequences[a], subdivisionSequence, weightSequence, subWeightSequences[a], level+1) 32 recursive_tree(subBinarySequences[a], subdivisionSequence, weightSequence, subWeightSequences[a], level+1)
32 33
33 #!!!! needs fixing
34 def are_parameters_valid(parameters):
35 areValid = True
36 # if 'Lmax' not in parameters :
37 34
38 def get_syncopation(bar, parameters = None): 35 def get_syncopation(bar, parameters = None):
39 del terminalNodes[:] 36 del terminalNodes[:]
40 syncopation = None 37 syncopation = None
41 38
42 binarySequence = bar.get_binary_sequence() 39 binarySequence = bar.get_binary_sequence()
43 subdivisionSequence = bar.get_subdivision_sequence() 40 subdivisionSequence = bar.get_subdivision_sequence()
44 41
42 # LHL can only measure monorhythms
45 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly': 43 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
46 print 'Warning: LHL model detects polyrhythms so returning None.' 44 print 'Warning: LHL model detects polyrhythms so returning None.'
47 else: 45 else:
48 # If the parameters are not given, use the default settings 46 # set defaults
49 if parameters == None: 47 Lmax = 5
50 Lmax = 5 48 weightSequence = range(0,-Lmax,-1)
51 weightSequence = range(0,-Lmax,-1) # i.e. [0,-1,-2,-3,-4] 49 # if parameters are specified by users, check their validities and update parameters if valid
50 if parameters!= None:
51 if 'Lmax' in parameters:
52 Lmax = parameters['Lmax']
53 if 'W' in parameters:
54 weightSequence = parameters['W']
55
56 if not are_parameters_valid(Lmax, weightSequence, subdivisionSequence):
57 print 'Error: the given parameters are not valid.'
52 else: 58 else:
53 if are_parameters_valid(parameters): 59 # If there is rhythm in previous bar, process its tree structure
54 Lmax = parameters['Lmax'] 60 if bar.get_previous_bar() != None:
55 weightSequence = parameters['W'] 61 prebarBinarySequence = bar.get_previous_bar().get_binary_sequence()
56 else: 62 recursive_tree(ceiling(prebarBinarySequence), subdivisionSequence, weightSequence, weightSequence[0],0)
57 pass 63
58 #raise InvalidParameterError 64 # Only keep the last note-type node
65 while terminalNodes[-1].nodeType != 'N':
66 del terminalNodes[-1]
67 del terminalNodes[0:-1]
59 68
60 # If there is rhythm in previous bar, process its tree structure 69 # For the rhythm in the current bar, process its tree structure and store the terminal nodes
61 if bar.get_previous_bar() != None: 70 recursive_tree(ceiling(binarySequence), subdivisionSequence, weightSequence, weightSequence[0],0)
62 prebarBinarySequence = bar.get_previous_bar().get_binary_sequence()
63 recursive_tree(ceiling(prebarBinarySequence), subdivisionSequence, weightSequence, weightSequence[0],0)
64 71
65 # Only keep the last note-type node 72 # for t in terminalNodes:
66 while terminalNodes[-1].nodeType != 'N': 73 # print '<', t.nodeType, t.metricalWeight, '>'
67 del terminalNodes[-1]
68 del terminalNodes[0:-1]
69 74
70 # For the rhythm in the current bar, process its tree structure and store the terminal nodes 75 # Search for the NR pairs that contribute to syncopation,then add the weight-difference to the NRpairSyncopation list
71 recursive_tree(ceiling(binarySequence), subdivisionSequence, weightSequence, weightSequence[0],0) 76 NRpairSyncopation = []
72 77 for i in range(len(terminalNodes)-1,0,-1):
73 # for t in terminalNodes: 78 if terminalNodes[i].nodeType == 'R':
74 # print '<', t.nodeType, t.metricalWeight, '>' 79 for j in range(i-1, -1, -1):
80 if (terminalNodes[j].nodeType == 'N') & (terminalNodes[i].metricalWeight >= terminalNodes[j].metricalWeight):
81 NRpairSyncopation.append(terminalNodes[i].metricalWeight - terminalNodes[j].metricalWeight)
82 break
83 #print NRpairSyncopation
75 84
76 # Search for the NR pairs that contribute to syncopation, 85 # If there are syncopation, sum all the local syncopation values stored in NRpairSyncopation list
77 # then add the weight-difference to the NRpairSyncopation list 86 if len(NRpairSyncopation) != 0:
78 NRpairSyncopation = [] 87 syncopation = sum(NRpairSyncopation)
79 for i in range(len(terminalNodes)-1,0,-1): 88 # If no syncopation, the value is -1;
80 if terminalNodes[i].nodeType == 'R': 89 elif len(terminalNodes) != 0:
81 for j in range(i-1, -1, -1): 90 syncopation = -1
82 if (terminalNodes[j].nodeType == 'N') & (terminalNodes[i].metricalWeight >= terminalNodes[j].metricalWeight):
83 NRpairSyncopation.append(terminalNodes[i].metricalWeight - terminalNodes[j].metricalWeight)
84 break
85 #print NRpairSyncopation
86
87 # If there are syncopation, sum all the local syncopation values stored in NRpairSyncopation list
88 if len(NRpairSyncopation) != 0:
89 syncopation = sum(NRpairSyncopation)
90 # If no syncopation, the value is -1;
91 elif len(terminalNodes) != 0:
92 syncopation = -1
93 91
94 return syncopation 92 return syncopation
95 93
96 94