Mercurial > hg > syncopation-dataset
view Syncopation models/LHL.py @ 2:031e2ccb1fb6
Added rhythm parser and parameter setter
author | Chunyang Song <csong@eecs.qmul.ac.uk> |
---|---|
date | Fri, 20 Mar 2015 18:28:08 +0000 |
parents | b2da092dc2e0 |
children | 4acddc008048 |
line wrap: on
line source
''' Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London ''' from BasicFuncs import concatenate, repeat, subdivide, ceiling terminal_nodes = [] # Global variable, storing all the terminal nodes from recursive tree structure in time order # Each terminnal node contains two properties: its node type (note or rest) and its metrical weight. class Node: def __init__(self,node_type,metrical_weight): self.node_type = node_type self.metrical_weight = metrical_weight # This function will recurse the tree for a binary sequence and return a sequence containing the terminal nodes in time order. def recursive_tree(seq, subdivision_seq, weight_seq, metrical_weight, level): if seq == concatenate([1],repeat([0],len(seq)-1)): # If matching to a Note type, add to terminal nodes terminal_nodes.append(Node('N',metrical_weight)) elif seq == repeat([0],len(seq)): # If matching to a Rest type, add to terminal nodes terminal_nodes.append(Node('R',metrical_weight)) else: # Keep subdividing by the subdivisor of the next level sub_seq = subdivide(seq, subdivision_seq[level+1]) sub_weight_seq = concatenate([metrical_weight],repeat([weight_seq[level+1]],subdivision_seq[level+1]-1)) for a in range(len(sub_seq)): recursive_tree(sub_seq[a], subdivision_seq, weight_seq, sub_weight_seq[a], level+1) # This function calculate syncoaption score for LHL model. def get_syncopation(seq, subdivision_seq, weight_seq, prebar_seq, rhythm_category): syncopation = None if rhythm_category == 'poly': print 'Error: LHL model cannot deal with polyrhythms.' else: # If there is rhythm in previous bar, process its tree structure if prebar_seq != None: recursive_tree(ceiling(prebar_seq), subdivision_seq, weight_seq, weight_seq[0],0) # Only keep the last note-type node while terminal_nodes[-1].node_type != 'N': del terminal_nodes[-1] del terminal_nodes[0:-1] # For the rhythm in the current bar, process its tree structure and store the terminal nodes recursive_tree(ceiling(seq), subdivision_seq, weight_seq, weight_seq[0],0) # for t in terminal_nodes: # print '<', t.node_type, t.metrical_weight, '>' # Search for the NR pairs that contribute to syncopation, add the weight-difference to the NR_pair_syncopation list NR_pair_syncopation = [] for i in range(len(terminal_nodes)-1,0,-1): if terminal_nodes[i].node_type == 'R': for j in range(i-1, -1, -1): if (terminal_nodes[j].node_type == 'N') & (terminal_nodes[i].metrical_weight >= terminal_nodes[j].metrical_weight): NR_pair_syncopation.append(terminal_nodes[i].metrical_weight - terminal_nodes[j].metrical_weight) break #print NR_pair_syncopation # If no syncopation, the value is -1; otherwise, sum all the local syncopation values stored in NR_pair_syncopation list if len(NR_pair_syncopation) != 0: syncopation = sum(NR_pair_syncopation) elif len(terminal_nodes) != 0: syncopation = -1 return syncopation