comparison Syncopation models/basic_functions.py @ 22:2dbc09ca8013

Refactored KTH, not tested yet. Added conversion functions between note sequence and velocity sequence, and tostring functions. Renamed get_min_timeSpan into velocity_sequence_to_min_timetpan, so need to refactor that.
author Chunyang Song <csong@eecs.qmul.ac.uk>
date Thu, 09 Apr 2015 23:49:16 +0100
parents b6daddeefda9
children df1e7c378ee0
comparison
equal deleted inserted replaced
21:b6daddeefda9 22:2dbc09ca8013
77 for odd in range(3, int(math.sqrt(number) + 1), 2): 77 for odd in range(3, int(math.sqrt(number) + 1), 2):
78 if number % odd == 0: 78 if number % odd == 0:
79 isPrime = False 79 isPrime = False
80 return isPrime 80 return isPrime
81 81
82 # The min_timeSpan function searches for the shortest possible time-span representation for a sequence. 82 # convert a velocity sequence to its minimum time-span representation
83 def get_min_timeSpan(seq): 83 def velocity_sequence_to_min_timetpan(velocitySequence):
84 minTimeSpan = [1] 84 minTimeSpanVelocitySeq = [1]
85 for d in find_divisor(len(seq)): 85 for divisors in find_divisor(len(velocitySequence)):
86 segments = subdivide(seq,d) 86 segments = subdivide(velocitySequence,divisors)
87 if len(segments)!=0: 87 if len(segments)!=0:
88 del minTimeSpan[:] 88 del minTimeSpanSequence[:]
89 for s in segments: 89 for s in segments:
90 minTimeSpan.append(s[0]) 90 minTimeSpanVelocitySeq.append(s[0])
91 if sum(minTimeSpan) == sum(seq): 91 if sum(minTimeSpanVelocitySeq) == sum(velocitySequence):
92 break 92 break
93 return minTimeSpan 93 return minTimeSpanVelocitySeq
94 94
95 # get_note_indices returns all the indices of all the notes in this sequence 95 # convert a note sequence to its minimum time-span representation
96 def get_note_indices(sequence): 96 def note_sequence_to_min_timespan(noteSequence, barTicks):
97 barBinaryArray = [0]*barTicks
98 for note in noteSequence:
99 # mark note_on event (i.e. startTime) and note_off event (i.e. endTime = startTime + duration) as 1 in the barBinaryArray
100 barBinaryArray[note[0]] = 1
101 barBinaryArray[note[0]+note[1]] = 1
102
103 # convert the barBinaryArray to its minimum time-span representation
104 minBarBinaryArray = velocitySequence_to_min_timeSpan(barBinaryArray)
105 delta_t = len(barBinaryArray)/len(minBarBinaryArray)
106
107 # scale the startTime and duration of each note by delta_t
108 for note in noteSequence:
109 note[0] = note[0]/delta_t
110 note[1] = note[1]/delta_t
111
112 return noteSequence
113
114
115
116 # get_note_indices returns all the indices of all the notes in this velocity_sequence
117 def get_note_indices(velocitySequence):
97 noteIndices = [] 118 noteIndices = []
98 119
99 for index in range(len(sequence)): 120 for index in range(len(velocitySequence)):
100 if sequence[index] != 0: 121 if velocitySequence[index] != 0:
101 noteIndices.append(index) 122 noteIndices.append(index)
102 123
103 return noteIndices 124 return noteIndices
125
104 126
105 # The get_H returns a sequence of metrical weight for a certain metrical level (horizontal), 127 # The get_H returns a sequence of metrical weight for a certain metrical level (horizontal),
106 # given the sequence of metrical weights in a hierarchy (vertical) and a sequence of subdivisions. 128 # given the sequence of metrical weights in a hierarchy (vertical) and a sequence of subdivisions.
107 def get_H(weightSequence,subdivisionSequence, level): 129 def get_H(weightSequence,subdivisionSequence, level):
108 H = [] 130 H = []
116 H = concatenate(H, concatenate([h], repeat([weightSequence[level]],subdivisionSequence[level]-1))) 138 H = concatenate(H, concatenate([h], repeat([weightSequence[level]],subdivisionSequence[level]-1)))
117 else: 139 else:
118 print 'Error: a subdivision factor or metrical weight is not defined for the request metrical level.' 140 print 'Error: a subdivision factor or metrical weight is not defined for the request metrical level.'
119 return H 141 return H
120 142
121 def calculate_time_span_ticks(numerator, denominator, ticksPerQuarter): 143
144 def calculate_bar_ticks(numerator, denominator, ticksPerQuarter):
122 return (numerator * ticksPerQuarter *4) / denominator 145 return (numerator * ticksPerQuarter *4) / denominator
146
147
148 def get_rhythm_category(velocitySequence, subdivisionSequence):
149 '''
150 The get_rhythm_category function is used to detect rhythm category: monorhythm or polyrhythm.
151 For monorhythms, all prime factors of the length of minimum time-span representation of this sequence are
152 elements of its subdivision_seq, otherwise it is polyrhythm;
153 e.g. prime_factors of polyrhythm 100100101010 in 4/4 is [2,3] but subdivision_seq = [1,2,2] for 4/4
154 '''
155 rhythmCategory = 'mono'
156 for f in find_prime_factors(len(get_min_timeSpan(velocitySequence))):
157 if not (f in subdivisionSequence):
158 rhythmCategory = 'poly'
159 break
160 return rhythmCategory
161
162
163 def string_to_sequence(inputString):
164 return map(int, inputString.split(','))
123 165
124 # # The get_subdivision_seq function returns the subdivision sequence of several common time-signatures defined by GTTM, 166 # # The get_subdivision_seq function returns the subdivision sequence of several common time-signatures defined by GTTM,
125 # # or ask for the top three level of subdivision_seq manually set by the user. 167 # # or ask for the top three level of subdivision_seq manually set by the user.
126 # def get_subdivision_seq(timesig, L_max): 168 # def get_subdivision_seq(timesig, L_max):
127 # subdivision_seq = [] 169 # subdivision_seq = []
154 # subdivision_seq = subdivision_seq[0:L_max+1] 196 # subdivision_seq = subdivision_seq[0:L_max+1]
155 197
156 # return subdivision_seq 198 # return subdivision_seq
157 199
158 200
159 def get_rhythm_category(velocitySequence, subdivisionSequence):
160 '''
161 The get_rhythm_category function is used to detect rhythm category: monorhythm or polyrhythm.
162 For monorhythms, all prime factors of the length of minimum time-span representation of this sequence are
163 elements of its subdivision_seq, otherwise it is polyrhythm;
164 e.g. prime_factors of polyrhythm 100100101010 in 4/4 is [2,3] but subdivision_seq = [1,2,2] for 4/4
165 '''
166 rhythmCategory = 'mono'
167 for f in find_prime_factors(len(get_min_timeSpan(velocitySequence))):
168 if not (f in subdivisionSequence):
169 rhythmCategory = 'poly'
170 break
171 return rhythmCategory
172
173 def string_to_sequence(inputString):
174 return map(int, inputString.split(','))
175
176
177 # The split_by_bar function seperates the score representation of rhythm by bar lines, 201 # The split_by_bar function seperates the score representation of rhythm by bar lines,
178 # resulting in a list representingbar-by-bar rhythm sequence, 202 # resulting in a list representingbar-by-bar rhythm sequence,
179 # e.g. rhythm = ['|',[ts1,td1,v1], [ts2,td2,v2], '|',[ts3,td3,v3],'|'...] 203 # e.g. rhythm = ['|',[ts1,td1,v1], [ts2,td2,v2], '|',[ts3,td3,v3],'|'...]
180 # rhythm_bybar = [ [ [ts1,td1,v1], [ts2,td2,v2] ], [ [ts3,td3,v3] ], [...]] 204 # rhythm_bybar = [ [ [ts1,td1,v1], [ts2,td2,v2] ], [ [ts3,td3,v3] ], [...]]
181 # def split_by_bar(rhythm): 205 # def split_by_bar(rhythm):