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

Added the R plots
author csong <csong@eecs.qmul.ac.uk>
date Thu, 23 Apr 2015 22:08:48 +0100
parents 273450d5980a
children
rev   line source
csong@1 1 '''
csong@1 2 Author: Chunyang Song
csong@1 3 Institution: Centre for Digital Music, Queen Mary University of London
csong@1 4
csong@1 5 '''
csong@1 6
csong@32 7 from basic_functions import get_note_indices, repeat, velocity_sequence_to_min_timespan
csong@1 8
csong@1 9 # To find the nearest power of 2 equal to or less than the given number
csong@20 10 def round_down_power_2(number):
csong@1 11 i = 0
csong@1 12 if number > 0:
csong@1 13 while pow(2,i) > number or number >= pow(2,i+1):
csong@1 14 i = i+1
csong@1 15 power2 = pow(2,i)
csong@1 16 else:
csong@1 17 print 'Error: numbers that are less than 1 cannot be rounded down to its nearest power of two.'
csong@1 18 power2 = None
csong@1 19 return power2
csong@1 20
csong@1 21 # To find the nearest power of 2 equal to or more than the given number
csong@20 22 def round_up_power_2(number):
csong@1 23 i = 0
csong@1 24 while pow(2,i) < number:
csong@1 25 i = i + 1
csong@1 26 return pow(2,i)
csong@1 27
csong@1 28 # To examine whether start_time is 'off-beat'
csong@22 29 def start_time_offbeat_measure(startTime, c_n):
csong@22 30 measure = 0
csong@20 31 if startTime % c_n != 0:
csong@22 32 measure = 2
csong@22 33 return measure
csong@1 34
csong@1 35 # To examine whether end_time is 'off-beat'
csong@22 36 def end_time_offbeat_measure(endTime, c_n):
csong@22 37 measure = 0
csong@20 38 if endTime % c_n != 0:
csong@22 39 measure = 1
csong@22 40 return measure
csong@1 41
csong@22 42 def get_syncopation(bar, parameters = None):
csong@21 43 syncopation = None
csong@1 44
csong@21 45 # KTH only deals with simple-duple meter where the number of beats per bar is a power of two.
csong@21 46 numerator = bar.get_time_signature().get_numerator()
csong@21 47 if numerator != round_down_power_2(numerator):
csong@21 48 print 'Warning: KTH model detects non simple-duple meter so returning None.'
csong@21 49 else:
csong@21 50 # retrieve note-sequence and next bar's note-sequence
csong@21 51 noteSequence = bar.get_note_sequence()
csong@23 52 #for note in noteSequence:
csong@23 53 # print note.to_string()
csong@23 54 #print 'barlength',bar.get_bar_ticks()
csong@23 55
csong@21 56 nextbarNoteSequence = None
csong@21 57 if bar.get_next_bar() != None:
csong@21 58 nextbarNoteSequence = bar.get_next_bar().get_note_sequence()
csong@1 59
csong@22 60 # convert note sequence to its minimum time-span representation so that the later calculation can be faster
csong@23 61 # noteSequence = note_sequence_to_min_timespan(noteSequence)
csong@23 62 # find delta_t
csong@23 63 Tmin = len(velocity_sequence_to_min_timespan(bar.get_velocity_sequence()))
csong@23 64 #print 'Tmin',Tmin
csong@23 65 T = round_up_power_2(Tmin)
csong@23 66 #print 'T',T
csong@23 67 deltaT = float(bar.get_bar_ticks())/T
csong@23 68 #print 'delta',deltaT
csong@23 69
csong@22 70
csong@22 71 # calculate syncopation note by note
csong@22 72 syncopation = 0
csong@22 73
csong@22 74 for note in noteSequence:
csong@23 75 c_n = round_down_power_2(note.duration/deltaT)
csong@23 76 #print 'd', note.duration
csong@23 77 #print 'c_n', c_n
csong@23 78 endTime = note.startTime + note.duration
csong@23 79 #print float(note.startTime)/deltaT, float(endTime)/deltaT
csong@23 80 syncopation = syncopation + start_time_offbeat_measure(float(note.startTime)/deltaT,c_n) + end_time_offbeat_measure(float(endTime)/deltaT,c_n)
csong@22 81
csong@21 82
csong@23 83 return syncopation
csong@21 84
csong@21 85 # # To calculate syncopation value of the sequence in the given time-signature.
csong@21 86 # def get_syncopation(seq, timesig, postbar_seq):
csong@21 87 # syncopation = 0
csong@21 88
csong@21 89 # numerator = int(timesig.split("/")[0])
csong@21 90 # if numerator == round_down_power_2(numerator): # if is a binary time-signature
csong@21 91 # # converting to minimum time-span format
csong@21 92 # seq = get_min_timeSpan(seq)
csong@21 93 # if postbar_seq != None:
csong@21 94 # postbar_seq = get_min_timeSpan(postbar_seq)
csong@21 95
csong@21 96 # # sf is a stretching factor matching rhythm sequence and meter, as Keith defines the note duration as a multiple of 1/(2^d) beats where d is number of metrical level
csong@21 97 # sf = round_up_power_2(len(seq))
csong@1 98
csong@21 99 # # retrieve all the indices of all the notes in this sequence
csong@21 100 # note_indices = get_note_indices(seq)
csong@1 101
csong@21 102 # for i in range(len(note_indices)):
csong@21 103 # # Assuming start_time is the index of this note, end_time is the index of the following note
csong@21 104 # start_time = note_indices[i]*sf/float(len(seq))
csong@1 105
csong@21 106 # if i == len(note_indices)-1: # if this is the last note, end_time is the index of the following note in the next bar
csong@21 107 # if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)):
csong@21 108 # next_index = get_note_indices(postbar_seq)[0]+len(seq)
csong@21 109 # end_time = next_index*sf/float(len(seq))
csong@21 110 # else: # or if the next bar is none or full rest, end_time is the end of this sequence.
csong@21 111 # end_time = sf
csong@21 112 # else:
csong@21 113 # end_time = note_indices[i+1]*sf/float(len(seq))
csong@1 114
csong@21 115 # duration = end_time - start_time
csong@21 116 # c_n = round_down_power_2(duration)
csong@21 117 # syncopation = syncopation + start(start_time,c_n) + end(end_time,c_n)
csong@21 118 # else:
csong@21 119 # print 'Error: KTH model can only deal with binary time-signature, e.g. 2/4 and 4/4. '
csong@21 120 # syncopation = None
csong@1 121
csong@21 122 # return syncopation