Mercurial > hg > syncopation-dataset
view Syncopation models/LHL.py @ 20:b959c2acb927
Refactored all models except for KTH, all past testing except for SG.
author | csong <csong@eecs.qmul.ac.uk> |
---|---|
date | Tue, 07 Apr 2015 19:05:07 +0100 |
parents | 9030967a05f8 |
children | 5de1cb45c145 |
line wrap: on
line source
''' Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London ''' from basic_functions import concatenate, repeat, subdivide, ceiling, get_rhythm_category terminalNodes = [] # 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,nodeType,metricalWeight): self.nodeType = nodeType self.metricalWeight = metricalWeight # This function will recurse the tree for a binary sequence and return a sequence containing the terminal nodes in time order. def recursive_tree(binarySequence, subdivisionSequence, weightSequence, metricalWeight, level): # If matching to a Note type, add to terminal nodes if binarySequence == concatenate([1],repeat([0],len(binarySequence)-1)): terminalNodes.append(Node('N',metricalWeight)) # If matching to a Rest type, add to terminal nodes elif binarySequence == repeat([0],len(binarySequence)): terminalNodes.append(Node('R',metricalWeight)) # Keep subdividing by the subdivisor of the next level else: subBinarySequences = subdivide(binarySequence, subdivisionSequence[level+1]) subWeightSequences = concatenate([metricalWeight],repeat([weightSequence[level+1]],subdivisionSequence[level+1]-1)) for a in range(len(subBinarySequences)): recursive_tree(subBinarySequences[a], subdivisionSequence, weightSequence, subWeightSequences[a], level+1) #!!!! needs fixing def are_parameters_valid(parameters): areValid = True # if 'Lmax' not in parameters : def get_syncopation(bar, parameters = None): del terminalNodes[:] syncopation = None binarySequence = bar.get_binary_sequence() subdivisionSequence = bar.get_subdivision_sequence() if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly': print 'Warning: LHL model detects polyrhythms so returning None.' else: # If the parameters are not given, use the default settings if parameters == None: Lmax = 5 weightSequence = range(0,-Lmax,-1) # i.e. [0,-1,-2,-3,-4] else: if are_parameters_valid(parameters): Lmax = parameters['Lmax'] weightSequence = parameters['W'] else: pass #raise InvalidParameterError # If there is rhythm in previous bar, process its tree structure if bar.get_previous_bar() != None: prebarBinarySequence = bar.get_previous_bar().get_binary_sequence() recursive_tree(ceiling(prebarBinarySequence), subdivisionSequence, weightSequence, weightSequence[0],0) # Only keep the last note-type node while terminalNodes[-1].nodeType != 'N': del terminalNodes[-1] del terminalNodes[0:-1] # For the rhythm in the current bar, process its tree structure and store the terminal nodes recursive_tree(ceiling(binarySequence), subdivisionSequence, weightSequence, weightSequence[0],0) # for t in terminalNodes: # print '<', t.nodeType, t.metricalWeight, '>' # Search for the NR pairs that contribute to syncopation, # then add the weight-difference to the NRpairSyncopation list NRpairSyncopation = [] for i in range(len(terminalNodes)-1,0,-1): if terminalNodes[i].nodeType == 'R': for j in range(i-1, -1, -1): if (terminalNodes[j].nodeType == 'N') & (terminalNodes[i].metricalWeight >= terminalNodes[j].metricalWeight): NRpairSyncopation.append(terminalNodes[i].metricalWeight - terminalNodes[j].metricalWeight) break #print NRpairSyncopation # If there are syncopation, sum all the local syncopation values stored in NRpairSyncopation list if len(NRpairSyncopation) != 0: syncopation = sum(NRpairSyncopation) # If no syncopation, the value is -1; elif len(terminalNodes) != 0: syncopation = -1 return syncopation