comparison Syncopation models/LHL.py @ 12:4acddc008048

Revised LHL and PRS model's argument list; refactored the variable names
author csong <csong@eecs.qmul.ac.uk>
date Fri, 03 Apr 2015 16:38:32 +0100
parents 031e2ccb1fb6
children 9030967a05f8
comparison
equal deleted inserted replaced
9:c2843ef4de2c 12:4acddc008048
1 ''' 1 '''
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 BasicFuncs import concatenate, repeat, subdivide, ceiling 6 from basic_functions import concatenate, repeat, subdivide, ceiling, get_rhythm_category
7 7
8 terminal_nodes = [] # Global variable, storing all the terminal nodes from recursive tree structure in time order 8 terminalNodes = [] # Global variable, storing all the terminal nodes from recursive tree structure in time order
9 9
10 # Each terminnal node contains two properties: its node type (note or rest) and its metrical weight. 10 # Each terminnal node contains two properties: its node type (note or rest) and its metrical weight.
11 class Node: 11 class Node:
12 def __init__(self,node_type,metrical_weight): 12 def __init__(self,nodeType,metricalWeight):
13 self.node_type = node_type 13 self.nodeType = nodeType
14 self.metrical_weight = metrical_weight 14 self.metricalWeight = metricalWeight
15 15
16 # This function will recurse the tree for a binary sequence and return a sequence containing the terminal nodes in time order. 16 # This function will recurse the tree for a binary sequence and return a sequence containing the terminal nodes in time order.
17 def recursive_tree(seq, subdivision_seq, weight_seq, metrical_weight, level): 17 def recursive_tree(binarySequence, subdivisionSequence, weightSequence, metricalWeight, level):
18 if seq == concatenate([1],repeat([0],len(seq)-1)): # If matching to a Note type, add to terminal nodes 18 # If matching to a Note type, add to terminal nodes
19 terminal_nodes.append(Node('N',metrical_weight)) 19 if binarySequence == concatenate([1],repeat([0],len(binarySequence)-1)):
20 terminalNodes.append(Node('N',metricalWeight))
20 21
21 elif seq == repeat([0],len(seq)): # If matching to a Rest type, add to terminal nodes 22 # If matching to a Rest type, add to terminal nodes
22 terminal_nodes.append(Node('R',metrical_weight)) 23 elif binarySequence == repeat([0],len(binarySequence)):
24 terminalNodes.append(Node('R',metricalWeight))
23 25
24 else: # Keep subdividing by the subdivisor of the next level 26 # Keep subdividing by the subdivisor of the next level
25 sub_seq = subdivide(seq, subdivision_seq[level+1]) 27 else:
26 sub_weight_seq = concatenate([metrical_weight],repeat([weight_seq[level+1]],subdivision_seq[level+1]-1)) 28 subBinarySequences = subdivide(binarySequence, subdivisionSequence[level+1])
27 for a in range(len(sub_seq)): 29 subWeightSequences = concatenate([metricalWeight],repeat([weightSequence[level+1]],subdivisionSequence[level+1]-1))
28 recursive_tree(sub_seq[a], subdivision_seq, weight_seq, sub_weight_seq[a], level+1) 30 for a in range(len(subBinarySequences)):
31 recursive_tree(subBinarySequences[a], subdivisionSequence, weightSequence, subWeightSequences[a], level+1)
29 32
30 # This function calculate syncoaption score for LHL model. 33 def get_syncopation(bar, weightSequence = None, LMax = None):
31 def get_syncopation(seq, subdivision_seq, weight_seq, prebar_seq, rhythm_category): 34 '''
35 The get_syncopation function calculates syncopation value .
36 '''
37 #def get_syncopation(seq, subdivision_seq, weight_seq, prebar_seq, rhythm_category):
32 syncopation = None 38 syncopation = None
33 if rhythm_category == 'poly': 39
34 print 'Error: LHL model cannot deal with polyrhythms.' 40 binarySequence = bar.get_binary_sequence()
41 subdivisionSequence = bar.get_subdivision_sequence()
42
43 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
44 print 'Warning: LHL model detects polyrhythms so returning None.'
35 else: 45 else:
46 if weightSequence == None:
47 if LMax == None:
48 LMax = 5
49 weightSequence = range(0,-LMax,-1)
50
36 # If there is rhythm in previous bar, process its tree structure 51 # If there is rhythm in previous bar, process its tree structure
37 if prebar_seq != None: 52 if bar.get_previous_bar() != None:
38 recursive_tree(ceiling(prebar_seq), subdivision_seq, weight_seq, weight_seq[0],0) 53 prebarBinarySequence = bar.get_previous_bar().get_binary_sequence()
54 recursive_tree(ceiling(prebarBinarySequence), subdivisionSequence, weightSequence, weightSequence[0],0)
39 55
40 # Only keep the last note-type node 56 # Only keep the last note-type node
41 while terminal_nodes[-1].node_type != 'N': 57 while terminalNodes[-1].node_type != 'N':
42 del terminal_nodes[-1] 58 del terminalNodes[-1]
43 del terminal_nodes[0:-1] 59 del terminalNodes[0:-1]
44 60
45 # For the rhythm in the current bar, process its tree structure and store the terminal nodes 61 # For the rhythm in the current bar, process its tree structure and store the terminal nodes
46 recursive_tree(ceiling(seq), subdivision_seq, weight_seq, weight_seq[0],0) 62 recursive_tree(ceiling(binarySequence), subdivisionSequence, weightSequence, weightSequence[0],0)
47 63
48 # for t in terminal_nodes: 64 # for t in terminalNodes:
49 # print '<', t.node_type, t.metrical_weight, '>' 65 # print '<', t.node_type, t.metrical_weight, '>'
50 66
51 # Search for the NR pairs that contribute to syncopation, add the weight-difference to the NR_pair_syncopation list 67 # Search for the NR pairs that contribute to syncopation,
52 NR_pair_syncopation = [] 68 # then add the weight-difference to the NRpairSyncopation list
53 for i in range(len(terminal_nodes)-1,0,-1): 69 NRpairSyncopation = []
54 if terminal_nodes[i].node_type == 'R': 70 for i in range(len(terminalNodes)-1,0,-1):
71 if terminalNodes[i].node_type == 'R':
55 for j in range(i-1, -1, -1): 72 for j in range(i-1, -1, -1):
56 if (terminal_nodes[j].node_type == 'N') & (terminal_nodes[i].metrical_weight >= terminal_nodes[j].metrical_weight): 73 if (terminalNodes[j].node_type == 'N') & (terminalNodes[i].metricalWeight >= terminalNodes[j].metricalWeight):
57 NR_pair_syncopation.append(terminal_nodes[i].metrical_weight - terminal_nodes[j].metrical_weight) 74 NRpairSyncopation.append(terminalNodes[i].metricalWeight - terminalNodes[j].metricalWeight)
58 break 75 break
59 #print NR_pair_syncopation 76 #print NRpairSyncopation
60 77
61 # If no syncopation, the value is -1; otherwise, sum all the local syncopation values stored in NR_pair_syncopation list 78 # If there are syncopation, sum all the local syncopation values stored in NRpairSyncopation list
62 if len(NR_pair_syncopation) != 0: 79 if len(NRpairSyncopation) != 0:
63 syncopation = sum(NR_pair_syncopation) 80 syncopation = sum(NRpairSyncopation)
64 elif len(terminal_nodes) != 0: 81 # If no syncopation, the value is -1;
82 elif len(terminalNodes) != 0:
65 syncopation = -1 83 syncopation = -1
66 84
67 return syncopation 85 return syncopation
86
87