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