Mercurial > hg > syncopation-dataset
view 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 |
line wrap: on
line source
''' Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London ** Pressing's model ** Algorithm: Only applicable to simple rhtyhms. Generate hierarchical metrical structure for rhythms, they way as same as LHL model; ''' def subdivide(sequence, segments_num): subSeq = [] if len(sequence) % segments_num != 0: print 'Error: rhythm segment cannot be equally subdivided ' else: n = len(sequence) / segments_num start , end = 0, n for i in range(segments_num): subSeq.append(sequence[start : end]) start = end end = end + n return subSeq # To check whether there is a need to continue subdividing and measuring def checkContinue(sequence, division): isContinue = False if len(sequence) % division == 0: subs = subdivide (sequence, division) for s in subs: if 1 in s[1:]: # If there are still onsets in-between the divisions isContinue = True else: print 'Error: the sequence cannot be equally subdivided!' return isContinue def timeSpanTranscribe(sequence): l = len(sequence) transcribe = [] if not (1 in sequence): # Full rest transcribe = [0] else: divisor = 1 while True: if l%divisor != 0: divisor = divisor + 1 else: sampleStep = l/divisor # how many digits in each segment, divisor also represents the number of segments template = (([1] + [0]*(sampleStep-1) ) * divisor ) sampled = [] for i in range(l): sampled.append(sequence[i] and template[i]) if sequence == sampled: break else: divisor = divisor + 1 subs = subdivide(sequence, divisor) for s in subs: transcribe.append(s[0]) return transcribe # Identify the type of rhythm sequence : 0- null; 1-filled; 2-run; 3-upbeat; 5-syncopated def syncType (sequence, followed_event): # Null is full rest or only one single on-beat note, therefore no 0 in sequence[1:] if not(1 in sequence[1:]) : syncType = 0 else: ts = timeSpanTranscribe(sequence) # Filled is equally spaced onsets, therefore all 1s in the time span transcribe of the sequence if not(0 in ts ): syncType = 1 # Run is either starting with 1 and end with 0 in time span, or starting with 1 if next bar starts with 0 elif ts[0] == 1 and ts[-1] == 0: syncType = 2 elif followed_event ==0 and ts[0] == 1: syncType = 2 # Upbeat requires next bars starting with 1 and at least the last event in time span is 1 elif followed_event == 1 and ts[-1] == 1: syncType = 3 # Syncopated start and end off-beat elif sequence[0] == 0: syncType = 5 else: print 'Error: un-recognizable syncopation type ', sequence syncType = None return syncType def createHierarchy(rhythm, time_sig, bar): h = [] # A list of lists to record syncopation type(s) in each hierarchy level across bars s_bar = subdivide (rhythm, bar) if '4/4' in time_sig: for i in range(bar): bar_level = s_bar[i] if i == bar -1: followed_event = s_bar[0][0] else: followed_event = s_bar[i+1][0] h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level if checkContinue(rhythm, 2*bar): for i in range(bar): s_halfBar = subdivide (s_bar[i], 2) halfBar_h = [] for j in range(2): halfBar_level = s_halfBar[j] if j == 1: followed_event = s_halfBar[0][0] else: followed_event = s_halfBar[j+1][0] halfBar_h.append (syncType (halfBar_level , followed_event)) h.append(halfBar_h) if checkContinue(rhythm, 4*bar): for i in range(bar): s_quarter = subdivide (s_bar[i], 4) quarter_h = [] for j in range(4): quarter_level = s_quarter [j] if j == 3: followed_event = s_quarter[0][0] else: followed_event = s_quarter[j+1][0] quarter_h. append ( syncType (quarter_level , followed_event) ) # quarter note level h.append(quarter_h) if checkContinue( rhythm, 8*bar): for i in range(bar): s_eighth = subdivide (s_bar[i], 8) eighth_h = [] for j in range(8): eighth_level = s_eighth [j] if j == 7: followed_event = eighth_level[0][0] else: followed_event = eighth_level[j+1][0] eighth_h.append (syncType (eighth_level, followed_event) ) h.append(eighth_h) elif '3/4' in time_sig: size_bar = len(s_bar) for i in range(size_bar): bar_level = s_bar[i] quarter_h = [] eighth_h = [] if i == size_bar -1: followed_event = s_bar[0][0] else: followed_event = s_bar[i+1][0] h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level if checkContinue(bar_level, 3): s_quarter = subdivide (bar_level, 3) size_quarter = len(s_quarter) for j in range(size_quarter): quarter_level = s_quarter [j] if j == size_quarter -1: followed_event = s_quarter[0][0] else: followed_event = s_quarter[j+1][0] quarter_h. append ( syncType (quarter_level , followed_event) ) # quarter note level if checkContinue( quarter_level, 2): s_eighth = subdivide (quarter_level, 2) # eighth note level size_eighth = len(s_eighth) for k in range(size_eighth): eighth_level = s_eighth [k] if k == size_eighth - 1: followed_event = eighth_level[0][0] else: followed_event = eighth_level[k+1][0] eighth_h.append (syncType (eighth_level, followed_event) ) h.append(eighth_h) h.append(quarter_h) elif '6/8' in time_sig: for i in range(bar): bar_level = s_bar[i] if i == bar -1: followed_event = s_bar[0][0] else: followed_event = s_bar[i+1][0] h. append ( [syncType(bar_level, followed_event)] ) # Indentify syncopation type at bar level if checkContinue(rhythm, 2*bar): for i in range(bar): s_halfBar = subdivide (s_bar[i], 2) halfBar_h = [] for j in range(2): halfBar_level = s_halfBar [j] if j == 1: followed_event = s_halfBar[0][0] else: followed_event = s_halfBar[j+1][0] halfBar_h. append ( syncType (halfBar_level , followed_event) ) h.append(halfBar_h) if checkContinue( rhythm, 6*bar): for i in range(bar): s_eighth = subdivide (s_bar[i], 6) # eighth note level eighth_h = [] for j in range(6): eighth_level = s_eighth [j] if j == 5: followed_event = eighth_level[0][0] else: followed_event = eighth_level[j+1][0] eighth_h.append (syncType (eighth_level, followed_event) ) h.append(eighth_h) else: print 'This time signature is not defined. Choose between 4/4, 3/4 or 6/8' return h def pressing(rhythm, time_sig, category, bar): sync_oneLevel = [] if 'poly' in category: return -1 else: hierarchy = createHierarchy(rhythm, time_sig, bar) # print 'h', hierarchy if len(hierarchy) != 0: for h in hierarchy: sync_oneLevel.append (sum(h) / float(len(h)) ) # Syncopation is the sum of averaged syncopation values of each level syncopation = sum (sync_oneLevel) else: syncopation = 0 return syncopation # Retrieve the stimuli # f = file('stimuli.txt') f = file('stimuli_34only.txt') #Calculate syncopation for each rhythm pattern while True: line = f.readline().split(';') if len(line) == 1: break else: sti_name = line[0] rhythmString = line[1].split() time_sig = line[2] category = line[3] bar = int([4]) rhythm = map(int,rhythmString[0].split(',')) print sti_name, pressing(rhythm, time_sig, category, bar)