annotate Syncopation models/SG.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
rev   line source
csong@0 1 '''
csong@0 2 Author: Chunyang Song
csong@0 3 Institution: Centre for Digital Music, Queen Mary University of London
csong@0 4
csong@0 5 ** Sioros and Guedes's Model **
csong@0 6
csong@0 7 Algorithm:
csong@0 8
csong@0 9 Only applicable to monorhythms.
csong@0 10
csong@0 11 This version of implementation follows the description in authors' 2011 ISMIR paper and assumes each bar of rhythm is looped.
csong@0 12 Therefore each bar is calculated seperatedly in a loop-mode and summed up in the end as the total syncopation.
csong@0 13
csong@0 14 '''
csong@0 15
csong@0 16 from MeterStructure import MeterStructure
csong@0 17 from math import pow
csong@0 18
csong@0 19 def subdivide(sequence, segments_num):
csong@0 20 subSeq = []
csong@0 21 if len(sequence) % segments_num != 0:
csong@0 22 print 'Error: rhythm segment cannot be equally subdivided '
csong@0 23 else:
csong@0 24 n = len(sequence) / segments_num
csong@0 25 start , end = 0, n
csong@0 26 for i in range(segments_num):
csong@0 27 subSeq.append(sequence[start : end])
csong@0 28 start = end
csong@0 29 end = end + n
csong@0 30
csong@0 31 return subSeq
csong@0 32
csong@0 33
csong@0 34 def sgModel(rhythm, time_sig, category, bar):
csong@0 35 ms = MeterStructure(time_sig)
csong@0 36 mWeights = ms.getLHLWeights(1)
csong@0 37 #print "hierarchy", mWeights
csong@0 38 num_onsets = 0
csong@0 39 h_min = min(mWeights)
csong@0 40
csong@0 41 syncAbsolute = 0
csong@0 42 syncNormM = 0
csong@0 43 syncNormE = 0
csong@0 44
csong@0 45 if 'poly' in category:
csong@0 46 syncAbsolute = -1
csong@0 47 else:
csong@0 48 # segment rhythm into bars
csong@0 49 rhythm_byBar = subdivide (rhythm, bar)
csong@0 50
csong@0 51 def measurePerBar(rhythm):
csong@0 52 syncopation = 0
csong@0 53
csong@0 54 def aveNeighbours(index, h):
csong@0 55 averages = []
csong@0 56 parameter_k = 0.8
csong@0 57
csong@0 58 def findPre(h_hat):
csong@0 59 pre_index = index - 1
csong@0 60 while(mWeights[pre_index] < h_hat):
csong@0 61 pre_index = (pre_index - 1)%len(mWeights)
csong@0 62 #print "h_hat and pre", h_hat, pre_index
csong@0 63 return pre_index
csong@0 64
csong@0 65 def findPost(h_hat):
csong@0 66 post_index = (index + 1)%len(mWeights)
csong@0 67 while(mWeights[post_index] < h_hat):
csong@0 68 post_index = (post_index + 1)%len(mWeights)
csong@0 69 #print "h_hat and post", h_hat, post_index
csong@0 70 return post_index
csong@0 71
csong@0 72 def dif(index1,index2):
csong@0 73 parameter_beta = 0.5
csong@0 74 pos1 = int(float(index1)/len(mWeights)*48)
csong@0 75 pos2 = int(float(index2)/len(mWeights)*48)
csong@0 76 dif_v = rhythm[pos1]-rhythm[pos2]
csong@0 77 dif_h = abs(mWeights[index1]-mWeights[index2])
csong@0 78 dif = dif_v*(parameter_beta*dif_h/4+1-parameter_beta)
csong@0 79 #print 'dif', dif
csong@0 80 return dif
csong@0 81
csong@0 82 for h_hat in range(h_min,h+1):
csong@0 83 ave = ( parameter_k*dif(index,findPre(h_hat))+dif(index,findPost(h_hat)) )/(1+parameter_k)
csong@0 84 #print 'ave', ave
csong@0 85 averages.append(ave)
csong@0 86
csong@0 87 return averages
csong@0 88
csong@0 89 for pos in range(len(rhythm)):
csong@0 90 if rhythm[pos] != 0: # Onset detected
csong@0 91 #num_onsets += 1
csong@0 92 i = int((pos/48.0*len(mWeights)))
csong@0 93 h = mWeights[i]
csong@0 94 potential = 1 - pow(0.5,(-h))
csong@0 95 #print "intermediate", min(aveNeighbours(i,h))
csong@0 96 syncopation += min(aveNeighbours(i, h))*potential
csong@0 97
csong@0 98 return syncopation
csong@0 99
csong@0 100 for r in rhythm_byBar:
csong@0 101 syncAbsolute = syncAbsolute + measurePerBar(r)
csong@0 102 #syncAbsolute /= 2.0
csong@0 103
csong@0 104 return syncAbsolute
csong@0 105
csong@0 106 # Retrieve the stimuli
csong@0 107 #f = file('stimuli.txt')
csong@0 108 #f = file('stimuli_34only.txt')
csong@0 109 f = file('clave.txt')
csong@0 110
csong@0 111
csong@0 112 #Calculate syncopation for each rhythm pattern
csong@0 113 #while True:
csong@0 114 for i in range(1):
csong@0 115 line = f.readline().split(';')
csong@0 116 if len(line) == 1:
csong@0 117 break
csong@0 118 else:
csong@0 119 sti_name = line[0]
csong@0 120 rhythmString = line[1].split()
csong@0 121 time_sig = line[2]
csong@0 122 category = line[3]
csong@0 123 bar = int(line[4])
csong@0 124
csong@0 125 rhythm = map(int,rhythmString[0].split(','))
csong@0 126 print sti_name, sgModel(rhythm, time_sig, category, bar)