Mercurial > hg > syncopation-dataset
diff Syncopation models/synpy/PRS.py @ 45:6e9154fc58df
moving the code files to the synpy package directory
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Thu, 23 Apr 2015 23:52:04 +0100 |
parents | |
children | e71028851131 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Syncopation models/synpy/PRS.py Thu Apr 23 23:52:04 2015 +0100 @@ -0,0 +1,73 @@ +''' +Author: Chunyang Song +Institution: Centre for Digital Music, Queen Mary University of London +''' + +from basic_functions import repeat, subdivide, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category + +def get_cost(sequence,nextSequence): + sequence = velocity_sequence_to_min_timespan(sequence) # converting to the minimum time-span format + + if sequence[1:] == repeat([0],len(sequence)-1): # null prototype + cost = 0 + elif sequence == repeat([1],len(sequence)): # filled prototype + cost = 1 + elif sequence[0] == 1 and sequence[-1] == 0: # run1 prototype + cost = 2 + elif sequence[0] == 1 and (nextSequence == None or nextSequence[0] == 0): # run2 prototype + cost = 2 + elif sequence[-1] == 1 and nextSequence != None and nextSequence[0] == 1: # upbeat prototype + cost = 3 + elif sequence[0] == 0: # syncopated prototype + cost = 5 + + return cost + +# This function calculates the syncopation value (cost) for the sequence with the postbar_seq for a certain level. +def syncopation_perlevel(subSequences): + #print 'subSequences', subSequences + total = 0 + for l in range(len(subSequences)-1): + #print 'cost', get_cost(subSequences[l], subSequences[l+1]) + total = total + get_cost(subSequences[l], subSequences[l+1]) + #print 'total this level', total + normalised = float(total)/(len(subSequences)-1) + + return normalised + +def get_syncopation(bar, parameters = None): + syncopation = None + + binarySequence = bar.get_binary_sequence() + subdivisionSequence = bar.get_subdivision_sequence() + + # PRS does not handle polyrhythms + if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly': + print 'Warning: PRS model detects polyrhythms so returning None.' + else: + syncopation = 0 + + # retrieve the binary sequence in the next bar + if bar.get_next_bar() != None: + nextbarBinarySequence = bar.get_next_bar().get_binary_sequence() + else: + nextbarBinarySequence = None + + # numberOfSubSeqs is the number of sub-sequences at a certain metrical level, initialised to be 1 (at the bar level) + numberOfSubSeqs = 1 + for subdivisor in subdivisionSequence: + # numberOfSubSeqs is product of all the subdivisors up to the current level + numberOfSubSeqs = numberOfSubSeqs * subdivisor + + # recursion stops when the length of sub-sequence is less than 2 + if len(binarySequence)/numberOfSubSeqs >= 2: + # generate sub-sequences and append the next bar sequence + subSequences = subdivide(ceiling(binarySequence), numberOfSubSeqs) + subSequences.append(nextbarBinarySequence) + # adding syncopation at each metrical level to the total syncopation + #print 'per level', syncopation_perlevel(subSequences) + syncopation += syncopation_perlevel(subSequences) + else: + break + + return syncopation