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