annotate Syncopation models/PRS.py @ 1:b2da092dc2e0

The consolidated syncopation software. Have finished individual model and basic functions. Need to revise the coding in main.py, and add rhythm-input interface.
author Chunyang Song <csong@eecs.qmul.ac.uk>
date Sun, 05 Oct 2014 21:52:41 +0100
parents 76ce27beba95
children 031e2ccb1fb6
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@1 6 from basic_functions import repeat, subdivide, ceiling, get_min_timeSpan
csong@1 7
csong@1 8 def get_cost(seq,next_seq):
csong@1 9 seq = get_min_timeSpan(seq) # converting to the minimum time-span format
csong@1 10
csong@1 11 if seq[1:] == repeat([0],len(seq)-1): # null prototype
csong@1 12 cost = 0
csong@1 13 elif seq == repeat([1],len(seq)): # filled prototype
csong@1 14 cost = 1
csong@1 15 elif seq[0] == 1 and seq[-1] == 0: # run1 prototype
csong@1 16 cost = 2
csong@1 17 elif seq[0] == 1 and (next_seq == None or next_seq[0] == 0): # run2 prototype
csong@1 18 cost = 2
csong@1 19 elif seq[0] == 1 and seq[-1] == 1 and next_seq != None and next_seq[0] == 1: # upbeat prototype
csong@1 20 cost = 3
csong@1 21 elif seq[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@1 27 def syncopation_perlevel(sub_seqs, num_subs):
csong@1 28 total = 0
csong@1 29 for l in range(num_subs):
csong@1 30 total = total + get_cost(sub_seqs[l], sub_seqs[l+1])
csong@1 31 normalised = float(total)/num_subs
csong@1 32
csong@1 33 return normalised
csong@1 34
csong@1 35 # This function calculates the overall syncopation value for a bar of sequence..
csong@1 36 def get_syncopation(seq,subdivision_seq, postbar_seq, rhythm_category):
csong@1 37 syncopation = None
csong@1 38 if rhythm_category == 'poly':
csong@1 39 print 'Error: PRS model cannot deal with polyrhythms.'
csong@0 40 else:
csong@1 41 syncopation = 0
csong@0 42
csong@1 43 current_num_subs = 1 # the initial number of sub-sequences at a certain metrical level
csong@1 44 for subdivisor in subdivision_seq:
csong@1 45 # the number of sub-sequence at the current level is product of all the subdivisors up to the current level
csong@1 46 current_num_subs = current_num_subs * subdivisor
csong@1 47 # recursion stops when the length of sub-sequence is less than 2
csong@1 48 if len(seq)/current_num_subs >= 2:
csong@1 49 # generate sub-sequences and append the next bar sequence
csong@1 50 sub_seqs = subdivide(ceiling(seq), current_num_subs)
csong@1 51 sub_seqs.append(postbar_seq)
csong@1 52 # adding syncopation at each metrical level to the total syncopation
csong@1 53 syncopation += syncopation_perlevel(sub_seqs, current_num_subs)
csong@1 54 else:
csong@1 55 break
csong@0 56
csong@1 57 return syncopation