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