Mercurial > hg > syncopation-dataset
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 |