annotate Syncopation models/PRS.py @ 42:121d0e1f1748

Added the R plots
author csong <csong@eecs.qmul.ac.uk>
date Thu, 23 Apr 2015 22:08:48 +0100
parents cc38b3047ed9
children
rev   line source
csong@0 1 '''
csong@0 2 Author: Chunyang Song
csong@0 3 Institution: Centre for Digital Music, Queen Mary University of London
csong@0 4 '''
csong@0 5
csong@23 6 from basic_functions import repeat, subdivide, ceiling, velocity_sequence_to_min_timespan, get_rhythm_category
csong@1 7
csong@12 8 def get_cost(sequence,nextSequence):
csong@23 9 sequence = velocity_sequence_to_min_timespan(sequence) # converting to the minimum time-span format
csong@1 10
csong@12 11 if sequence[1:] == repeat([0],len(sequence)-1): # null prototype
csong@1 12 cost = 0
csong@12 13 elif sequence == repeat([1],len(sequence)): # filled prototype
csong@1 14 cost = 1
csong@12 15 elif sequence[0] == 1 and sequence[-1] == 0: # run1 prototype
csong@1 16 cost = 2
csong@20 17 elif sequence[0] == 1 and (nextSequence == None or nextSequence[0] == 0): # run2 prototype
csong@1 18 cost = 2
csong@20 19 elif sequence[-1] == 1 and nextSequence != None and nextSequence[0] == 1: # upbeat prototype
csong@1 20 cost = 3
csong@12 21 elif sequence[0] == 0: # syncopated prototype
csong@1 22 cost = 5
csong@1 23
csong@1 24 return cost
csong@1 25
csong@1 26 # This function calculates the syncopation value (cost) for the sequence with the postbar_seq for a certain level.
csong@12 27 def syncopation_perlevel(subSequences):
christopher@38 28 #print 'subSequences', subSequences
csong@1 29 total = 0
csong@12 30 for l in range(len(subSequences)-1):
christopher@38 31 #print 'cost', get_cost(subSequences[l], subSequences[l+1])
csong@12 32 total = total + get_cost(subSequences[l], subSequences[l+1])
christopher@38 33 #print 'total this level', total
csong@12 34 normalised = float(total)/(len(subSequences)-1)
csong@1 35
csong@1 36 return normalised
csong@1 37
csong@19 38 def get_syncopation(bar, parameters = None):
csong@1 39 syncopation = None
csong@12 40
csong@12 41 binarySequence = bar.get_binary_sequence()
csong@12 42 subdivisionSequence = bar.get_subdivision_sequence()
csong@12 43
csong@20 44 # PRS does not handle polyrhythms
csong@12 45 if get_rhythm_category(binarySequence, subdivisionSequence) == 'poly':
csong@12 46 print 'Warning: PRS model detects polyrhythms so returning None.'
csong@0 47 else:
csong@1 48 syncopation = 0
csong@0 49
csong@20 50 # retrieve the binary sequence in the next bar
csong@12 51 if bar.get_next_bar() != None:
csong@12 52 nextbarBinarySequence = bar.get_next_bar().get_binary_sequence()
csong@12 53 else:
csong@12 54 nextbarBinarySequence = None
csong@12 55
csong@20 56 # numberOfSubSeqs is the number of sub-sequences at a certain metrical level, initialised to be 1 (at the bar level)
csong@12 57 numberOfSubSeqs = 1
csong@12 58 for subdivisor in subdivisionSequence:
csong@20 59 # numberOfSubSeqs is product of all the subdivisors up to the current level
csong@12 60 numberOfSubSeqs = numberOfSubSeqs * subdivisor
csong@20 61
csong@1 62 # recursion stops when the length of sub-sequence is less than 2
csong@12 63 if len(binarySequence)/numberOfSubSeqs >= 2:
csong@1 64 # generate sub-sequences and append the next bar sequence
csong@12 65 subSequences = subdivide(ceiling(binarySequence), numberOfSubSeqs)
csong@12 66 subSequences.append(nextbarBinarySequence)
csong@1 67 # adding syncopation at each metrical level to the total syncopation
csong@20 68 #print 'per level', syncopation_perlevel(subSequences)
csong@12 69 syncopation += syncopation_perlevel(subSequences)
csong@1 70 else:
csong@1 71 break
csong@0 72
csong@1 73 return syncopation