Mercurial > hg > syncopation-dataset
view Syncopation models/SG.py @ 2:031e2ccb1fb6
Added rhythm parser and parameter setter
author | Chunyang Song <csong@eecs.qmul.ac.uk> |
---|---|
date | Fri, 20 Mar 2015 18:28:08 +0000 |
parents | b2da092dc2e0 |
children | b959c2acb927 |
line wrap: on
line source
''' Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London ''' from BasicFuncs import get_H, get_min_timeSpan def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): syncopation = None if rhythm_category == 'poly': print 'Error: SG model cannot deal with polyrhythms.' else: seq = get_min_timeSpan(seq) # converting to the minimum time-span format # checking whether the given L_max is enough to analyse the given sequence, if not, request a bigger L_max new_L_max = True matching_level = L_max while matching_level >= 0: if len(get_H(weight_seq,subdivision_seq, matching_level)) == len(seq): new_L_max = False break else: matching_level = matching_level - 1 if new_L_max == True: print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.' else: syncopation = 0 # generate the metrical weights of the lowest level H = get_H(weight_seq,subdivision_seq, matching_level) # The aveDif_neighbours function calculates the (weighted) average of the difference between the note at a certain index and its neighbours in a certain metrical level def aveDif_neighbours(index, level): averages = [] parameter_garma = 0.8 # The findPre function is to calculate the index of the previous neighbour at a certain metrical level. def findPre(index, level): pre_index = (index - 1)%len(H) while(H[pre_index] > level): pre_index = (pre_index - 1)%len(H) return pre_index # The findPost function is to calculate the index of the next neighbour at a certain metrical level. def findPost(index, level): post_index = (index + 1)%len(H) while(H[post_index] > level): post_index = (post_index + 1)%len(H) return post_index # The dif function is to calculate a difference level factor between two notes (at note position index1 and index 2) in velocity sequence def dif(index1,index2): parameter_beta = 0.5 dif_v = seq[index1]-seq[index2] dif_h = abs(H[index1]-H[index2]) dif = dif_v*(parameter_beta*dif_h/4+1-parameter_beta) return dif # From the highest to the lowest metrical levels where the current note resides, calculate the difference between the note and its neighbours at that level for l in range(level, max(H)+1): ave = ( parameter_garma*dif(index,findPre(index,l))+dif(index,findPost(index,l)) )/(1+parameter_garma) averages.append(ave) return averages # Calculate the syncopation value for each note for index in range(len(seq)): if seq[index] != 0: # Onset detected h = H[index] potential = 1 - pow(0.5,h) # Syncopation potential according to its metrical level, which is equal to the metrical weight level = h # Metrical weight happens to be equal to its metrical level syncopation += min(aveDif_neighbours(index, h))*potential return syncopation