Mercurial > hg > syncopation-dataset
diff Syncopation models/TMC.py @ 1:b2da092dc2e0
The consolidated syncopation software. Have finished individual model and basic functions. Need to revise the coding in main.py, and add rhythm-input interface.
author | Chunyang Song <csong@eecs.qmul.ac.uk> |
---|---|
date | Sun, 05 Oct 2014 21:52:41 +0100 |
parents | 76ce27beba95 |
children | 031e2ccb1fb6 |
line wrap: on
line diff
--- a/Syncopation models/TMC.py Fri Mar 21 15:49:46 2014 +0000 +++ b/Syncopation models/TMC.py Sun Oct 05 21:52:41 2014 +0100 @@ -2,71 +2,54 @@ Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London -** Toussaint's Metric Complexity Model ** - -Algorithm: - -Only applicable to monorhythms. - -Define metrical hierarchy by given time signature; -Calculate how many onsets and determine Maximum Metricality Max_Metric; -Calculate the Metrical Simplicity - the weights of all onsets; -Syncopation = Max_Metric - Metric_simplicity. -Output the predicted syncopation score; -1 indicates non-applicable - ''' -from MeterStructure import MeterStructure +from basic_functions import get_H, ceiling, get_min_timeSpan -def metricalModel(rhythm, time_sig, category, bar): - ms = MeterStructure(time_sig) - meter = ms.getLJWeights(bar) - if len(meter) !=0: +# The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level. +def get_metricity(seq, H): + metricity = 0 + for m in range(len(seq)): + metricity = metricity + seq[m]*H[m] + return metricity + +# The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence. +def get_max_metricity(seq, H): + max_metricity = 0 + H.sort(reverse=True) # Sort the metrical weight sequence from large to small + for i in range(sum(seq)): + max_metricity = max_metricity+H[i] + return max_metricity + +# The get_syncopation function calculates the syncopation value of the given sequence for TMC model. +def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category): + syncopation = None + if rhythm_category == 'poly': + print 'Error: TMC 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.' - metricalSimplicity = 0 # sum of weights of onsets per bar - maxMetrical = 0 # maximum metricity per bar - onsetCount = 0 # The number of onsets per bar - - if 'poly' in category: # not applicable to polyrhythms - return -1 - - # Calculate metricalSimplicity else: - l = len(rhythm) - for i in range(l): - if rhythm[i] == 1: # onset detected - pos = int((float(i)/l) *len(meter)) # looking for the metrical position where this note locates - metricalSimplicity = metricalSimplicity+meter[pos] - onsetCount = onsetCount+1 - - # Calculate max metricity - meter.sort(reverse=True) - for i in range(0,onsetCount): - maxMetrical = maxMetrical+meter[i] + # generate the metrical weights of the lowest level, + # using the last matching_level number of elements in the weight_seq list, to make sure the last element is 1 + H = get_H (weight_seq[-(matching_level+1):], subdivision_seq, matching_level) - #print 'test', onsetCount, maxMetrical, metricalSimplicity - syncopation = (maxMetrical - metricalSimplicity) - - return syncopation - else: - return -1 + metricity = get_metricity(ceiling(seq), H) # converting to binary sequence then calculate metricity + max_metricity = get_max_metricity(ceiling(seq), H) -# Retrieve the stimuli -f = file('stimuli.txt') -#f = file('stimuli_34only.txt') + syncopation = max_metricity - metricity + return syncopation -#Calculate syncopation for each rhythm pattern -while True: - line = f.readline().split(';') - if len(line) == 1: - break - else: - sti_name = line[0] - rhythmString = line[1].split() - time_sig = line[2] - category = line[3] - bar = int(line[4]) - - rhythm = map(int,rhythmString[0].split(',')) - - print sti_name, metricalModel(rhythm, time_sig, category, bar)