comparison Syncopation models/PRS.py @ 0:76ce27beba95

Have uploaded the syncopation dataset and audio wavefies.
author Chunyang Song <csong@eecs.qmul.ac.uk>
date Fri, 21 Mar 2014 15:49:46 +0000
parents
children b2da092dc2e0
comparison
equal deleted inserted replaced
-1:000000000000 0:76ce27beba95
1 '''
2 Author: Chunyang Song
3 Institution: Centre for Digital Music, Queen Mary University of London
4
5 ** Pressing's model **
6
7 Algorithm:
8
9 Only applicable to simple rhtyhms.
10
11 Generate hierarchical metrical structure for rhythms, they way as same as LHL model;
12
13
14 '''
15
16 def subdivide(sequence, segments_num):
17 subSeq = []
18 if len(sequence) % segments_num != 0:
19 print 'Error: rhythm segment cannot be equally subdivided '
20 else:
21 n = len(sequence) / segments_num
22 start , end = 0, n
23 for i in range(segments_num):
24 subSeq.append(sequence[start : end])
25 start = end
26 end = end + n
27
28 return subSeq
29
30 # To check whether there is a need to continue subdividing and measuring
31 def checkContinue(sequence, division):
32 isContinue = False
33 if len(sequence) % division == 0:
34 subs = subdivide (sequence, division)
35
36 for s in subs:
37 if 1 in s[1:]: # If there are still onsets in-between the divisions
38 isContinue = True
39 else:
40 print 'Error: the sequence cannot be equally subdivided!'
41 return isContinue
42
43 def timeSpanTranscribe(sequence):
44 l = len(sequence)
45 transcribe = []
46
47 if not (1 in sequence): # Full rest
48 transcribe = [0]
49 else:
50 divisor = 1
51 while True:
52 if l%divisor != 0:
53 divisor = divisor + 1
54 else:
55 sampleStep = l/divisor # how many digits in each segment, divisor also represents the number of segments
56 template = (([1] + [0]*(sampleStep-1) ) * divisor )
57
58 sampled = []
59 for i in range(l):
60 sampled.append(sequence[i] and template[i])
61
62 if sequence == sampled:
63 break
64 else:
65 divisor = divisor + 1
66
67 subs = subdivide(sequence, divisor)
68 for s in subs:
69 transcribe.append(s[0])
70
71 return transcribe
72
73 # Identify the type of rhythm sequence : 0- null; 1-filled; 2-run; 3-upbeat; 5-syncopated
74 def syncType (sequence, followed_event):
75
76 # Null is full rest or only one single on-beat note, therefore no 0 in sequence[1:]
77 if not(1 in sequence[1:]) :
78 syncType = 0
79
80 else:
81 ts = timeSpanTranscribe(sequence)
82
83 # Filled is equally spaced onsets, therefore all 1s in the time span transcribe of the sequence
84 if not(0 in ts ):
85 syncType = 1
86 # Run is either starting with 1 and end with 0 in time span, or starting with 1 if next bar starts with 0
87 elif ts[0] == 1 and ts[-1] == 0:
88 syncType = 2
89 elif followed_event ==0 and ts[0] == 1:
90 syncType = 2
91 # Upbeat requires next bars starting with 1 and at least the last event in time span is 1
92 elif followed_event == 1 and ts[-1] == 1:
93 syncType = 3
94 # Syncopated start and end off-beat
95 elif sequence[0] == 0:
96 syncType = 5
97 else:
98 print 'Error: un-recognizable syncopation type ', sequence
99 syncType = None
100
101 return syncType
102
103 def createHierarchy(rhythm, time_sig, bar):
104 h = [] # A list of lists to record syncopation type(s) in each hierarchy level across bars
105 s_bar = subdivide (rhythm, bar)
106
107 if '4/4' in time_sig:
108
109 for i in range(bar):
110 bar_level = s_bar[i]
111
112 if i == bar -1:
113 followed_event = s_bar[0][0]
114 else:
115 followed_event = s_bar[i+1][0]
116
117 h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level
118
119 if checkContinue(rhythm, 2*bar):
120
121 for i in range(bar):
122 s_halfBar = subdivide (s_bar[i], 2)
123 halfBar_h = []
124
125 for j in range(2):
126 halfBar_level = s_halfBar[j]
127
128 if j == 1:
129 followed_event = s_halfBar[0][0]
130 else:
131 followed_event = s_halfBar[j+1][0]
132
133 halfBar_h.append (syncType (halfBar_level , followed_event))
134
135 h.append(halfBar_h)
136
137 if checkContinue(rhythm, 4*bar):
138
139 for i in range(bar):
140 s_quarter = subdivide (s_bar[i], 4)
141 quarter_h = []
142
143 for j in range(4):
144 quarter_level = s_quarter [j]
145
146 if j == 3:
147 followed_event = s_quarter[0][0]
148 else:
149 followed_event = s_quarter[j+1][0]
150
151 quarter_h. append ( syncType (quarter_level , followed_event) ) # quarter note level
152
153 h.append(quarter_h)
154
155 if checkContinue( rhythm, 8*bar):
156
157 for i in range(bar):
158 s_eighth = subdivide (s_bar[i], 8)
159 eighth_h = []
160
161 for j in range(8):
162 eighth_level = s_eighth [j]
163
164 if j == 7:
165 followed_event = eighth_level[0][0]
166 else:
167 followed_event = eighth_level[j+1][0]
168
169 eighth_h.append (syncType (eighth_level, followed_event) )
170
171 h.append(eighth_h)
172
173
174 elif '3/4' in time_sig:
175 size_bar = len(s_bar)
176 for i in range(size_bar):
177 bar_level = s_bar[i]
178
179 quarter_h = []
180 eighth_h = []
181
182 if i == size_bar -1:
183 followed_event = s_bar[0][0]
184 else:
185 followed_event = s_bar[i+1][0]
186
187 h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level
188
189 if checkContinue(bar_level, 3):
190 s_quarter = subdivide (bar_level, 3)
191 size_quarter = len(s_quarter)
192
193 for j in range(size_quarter):
194 quarter_level = s_quarter [j]
195
196 if j == size_quarter -1:
197 followed_event = s_quarter[0][0]
198 else:
199 followed_event = s_quarter[j+1][0]
200
201 quarter_h. append ( syncType (quarter_level , followed_event) ) # quarter note level
202
203 if checkContinue( quarter_level, 2):
204 s_eighth = subdivide (quarter_level, 2) # eighth note level
205 size_eighth = len(s_eighth)
206
207 for k in range(size_eighth):
208 eighth_level = s_eighth [k]
209
210 if k == size_eighth - 1:
211 followed_event = eighth_level[0][0]
212 else:
213 followed_event = eighth_level[k+1][0]
214
215 eighth_h.append (syncType (eighth_level, followed_event) )
216 h.append(eighth_h)
217
218 h.append(quarter_h)
219
220
221 elif '6/8' in time_sig:
222 for i in range(bar):
223 bar_level = s_bar[i]
224
225 if i == bar -1:
226 followed_event = s_bar[0][0]
227 else:
228 followed_event = s_bar[i+1][0]
229
230 h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level
231
232 if checkContinue(rhythm, 2*bar):
233
234 for i in range(bar):
235 s_halfBar = subdivide (s_bar[i], 2)
236 halfBar_h = []
237
238 for j in range(2):
239 halfBar_level = s_halfBar [j]
240
241 if j == 1:
242 followed_event = s_halfBar[0][0]
243 else:
244 followed_event = s_halfBar[j+1][0]
245
246 halfBar_h. append ( syncType (halfBar_level , followed_event) )
247
248 h.append(halfBar_h)
249
250 if checkContinue( rhythm, 6*bar):
251
252 for i in range(bar):
253 s_eighth = subdivide (s_bar[i], 6) # eighth note level
254 eighth_h = []
255
256 for j in range(6):
257 eighth_level = s_eighth [j]
258
259 if j == 5:
260 followed_event = eighth_level[0][0]
261 else:
262 followed_event = eighth_level[j+1][0]
263
264 eighth_h.append (syncType (eighth_level, followed_event) )
265
266 h.append(eighth_h)
267
268 else:
269 print 'This time signature is not defined. Choose between 4/4, 3/4 or 6/8'
270
271 return h
272
273
274 def pressing(rhythm, time_sig, category, bar):
275 sync_oneLevel = []
276
277 if 'poly' in category:
278 return -1
279
280 else:
281 hierarchy = createHierarchy(rhythm, time_sig, bar)
282 # print 'h', hierarchy
283
284 if len(hierarchy) != 0:
285 for h in hierarchy:
286 sync_oneLevel.append (sum(h) / float(len(h)) )
287
288 # Syncopation is the sum of averaged syncopation values of each level
289 syncopation = sum (sync_oneLevel)
290
291 else:
292 syncopation = 0
293
294 return syncopation
295
296
297 # Retrieve the stimuli
298 # f = file('stimuli.txt')
299 f = file('stimuli_34only.txt')
300
301 #Calculate syncopation for each rhythm pattern
302 while True:
303 line = f.readline().split(';')
304 if len(line) == 1:
305 break
306 else:
307 sti_name = line[0]
308 rhythmString = line[1].split()
309 time_sig = line[2]
310 category = line[3]
311 bar = int([4])
312
313 rhythm = map(int,rhythmString[0].split(','))
314
315 print sti_name, pressing(rhythm, time_sig, category, bar)
316