Mercurial > hg > syncopation-dataset
diff Syncopation models/SG.py @ 20:b959c2acb927
Refactored all models except for KTH, all past testing except for SG.
author | csong <csong@eecs.qmul.ac.uk> |
---|---|
date | Tue, 07 Apr 2015 19:05:07 +0100 |
parents | 031e2ccb1fb6 |
children | df1e7c378ee0 |
line wrap: on
line diff
--- a/Syncopation models/SG.py Fri Apr 03 22:57:27 2015 +0100 +++ b/Syncopation models/SG.py Tue Apr 07 19:05:07 2015 +0100 @@ -4,73 +4,85 @@ ''' -from BasicFuncs import get_H, get_min_timeSpan +from basic_functions import get_H, get_min_timeSpan, get_rhythm_category +from TMC import find_L -def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): +#def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): +def get_syncopation(bar, parameters = None): syncopation = None - if rhythm_category == 'poly': - print 'Error: SG model cannot deal with polyrhythms.' + velocitySequence = bar.get_velocity_sequence() + subdivisionSequence = bar.get_subdivision_sequence() + + if get_rhythm_category(velocitySequence, subdivisionSequence) == 'poly': + print 'Warning: SG model detects polyrhythms so returning None.' 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 + velocitySequence = get_min_timeSpan(velocitySequence) # converting to the minimum time-span format + + # If the parameters are not given, use the default settings + if parameters == None: + Lmax = 5 + weightSequence = range(Lmax+1) # i.e. [0,1,2,3,4,5] + else: + if are_parameters_valid(parameters): + Lmax = parameters['Lmax'] + weightSequence = parameters['W'] else: - matching_level = matching_level - 1 + pass + #raise InvalidParameterError - 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: + L = find_L(velocitySequence, Lmax, weightSequence, subdivisionSequence) + print 'L', L + if L != None: syncopation = 0 # generate the metrical weights of the lowest level - H = get_H(weight_seq,subdivision_seq, matching_level) + H = get_H(weightSequence,subdivisionSequence, L) + print 'H', H - # 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): + # The ave_dif_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 ave_dif_neighbours(index, level): + averages = [] - parameter_garma = 0.8 + parameterGarma = 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 + def find_pre(index, level): + preIndex = (index - 1)%len(H) # using % is to restrict the index varies within range(0, len(H)) + while(H[preIndex] > level): + preIndex = (preIndex - 1)%len(H) + print 'preIndex', preIndex + return preIndex # 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 + def find_post(index, level): + postIndex = (index + 1)%len(H) + while(H[postIndex] > level): + postIndex = (postIndex + 1)%len(H) + print 'postIndex', postIndex + return postIndex # 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] + parameterBeta = 0.5 + dif_v = velocitySequence[index1]-velocitySequence[index2] dif_h = abs(H[index1]-H[index2]) - dif = dif_v*(parameter_beta*dif_h/4+1-parameter_beta) + dif = dif_v*(parameterBeta*dif_h/4+1-parameterBeta) + print 'dif', dif 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) + ave = (parameterGarma*dif(index,find_pre(index,l))+dif(index,find_post(index,l)) )/(1+parameterGarma) averages.append(ave) + print 'averages', averages 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 + for index in range(len(velocitySequence)): + if velocitySequence[index] != 0: # Onset detected + h = H[index] + # Syncopation potential according to its metrical level, which is equal to the metrical weight + potential = 1 - pow(0.5,h) + level = h # Metrical weight is equal to its metrical level + syncopation += min(ave_dif_neighbours(index, level))*potential return syncopation