comparison 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
comparison
equal deleted inserted replaced
0:76ce27beba95 1:b2da092dc2e0
1 ''' 1 '''
2 Author: Chunyang Song 2 Author: Chunyang Song
3 Institution: Centre for Digital Music, Queen Mary University of London 3 Institution: Centre for Digital Music, Queen Mary University of London
4 4
5 ** Toussaint's Metric Complexity Model **
6
7 Algorithm:
8
9 Only applicable to monorhythms.
10
11 Define metrical hierarchy by given time signature;
12 Calculate how many onsets and determine Maximum Metricality Max_Metric;
13 Calculate the Metrical Simplicity - the weights of all onsets;
14 Syncopation = Max_Metric - Metric_simplicity.
15 Output the predicted syncopation score; -1 indicates non-applicable
16
17 ''' 5 '''
18 6
19 from MeterStructure import MeterStructure 7 from basic_functions import get_H, ceiling, get_min_timeSpan
20 8
21 def metricalModel(rhythm, time_sig, category, bar): 9 # The get_metricity function calculates the metricity for a binary sequence with given sequence of metrical weights in a certain metrical level.
22 ms = MeterStructure(time_sig) 10 def get_metricity(seq, H):
23 meter = ms.getLJWeights(bar) 11 metricity = 0
24 if len(meter) !=0: 12 for m in range(len(seq)):
13 metricity = metricity + seq[m]*H[m]
14 return metricity
15
16 # The get_max_metricity function calculates the maximum metricity for the same number of notes in a binary sequence.
17 def get_max_metricity(seq, H):
18 max_metricity = 0
19 H.sort(reverse=True) # Sort the metrical weight sequence from large to small
20 for i in range(sum(seq)):
21 max_metricity = max_metricity+H[i]
22 return max_metricity
23
24 # The get_syncopation function calculates the syncopation value of the given sequence for TMC model.
25 def get_syncopation(seq, subdivision_seq, weight_seq, L_max, rhythm_category):
26 syncopation = None
27 if rhythm_category == 'poly':
28 print 'Error: TMC model cannot deal with polyrhythms.'
29 else:
30 seq = get_min_timeSpan(seq) # converting to the minimum time-span format
31
32 # checking whether the given L_max is enough to analyse the given sequence, if not, request a bigger L_max
33 new_L_max = True
34 matching_level = L_max
35 while matching_level >= 0:
36 if len(get_H(weight_seq,subdivision_seq, matching_level)) == len(seq):
37 new_L_max = False
38 break
39 else:
40 matching_level = matching_level - 1
41
42 if new_L_max == True:
43 print 'Error: needs a bigger L_max (i.e. the lowest metrical level) to match the given rhythm sequence.'
25 44
26 metricalSimplicity = 0 # sum of weights of onsets per bar
27 maxMetrical = 0 # maximum metricity per bar
28 onsetCount = 0 # The number of onsets per bar
29
30 if 'poly' in category: # not applicable to polyrhythms
31 return -1
32
33 # Calculate metricalSimplicity
34 else: 45 else:
35 l = len(rhythm) 46 # generate the metrical weights of the lowest level,
36 for i in range(l): 47 # using the last matching_level number of elements in the weight_seq list, to make sure the last element is 1
37 if rhythm[i] == 1: # onset detected 48 H = get_H (weight_seq[-(matching_level+1):], subdivision_seq, matching_level)
38 pos = int((float(i)/l) *len(meter)) # looking for the metrical position where this note locates
39 metricalSimplicity = metricalSimplicity+meter[pos]
40 onsetCount = onsetCount+1
41
42 # Calculate max metricity
43 meter.sort(reverse=True)
44 for i in range(0,onsetCount):
45 maxMetrical = maxMetrical+meter[i]
46 49
47 #print 'test', onsetCount, maxMetrical, metricalSimplicity 50 metricity = get_metricity(ceiling(seq), H) # converting to binary sequence then calculate metricity
48 syncopation = (maxMetrical - metricalSimplicity) 51 max_metricity = get_max_metricity(ceiling(seq), H)
49
50 return syncopation
51 else:
52 return -1
53 52
54 # Retrieve the stimuli 53 syncopation = max_metricity - metricity
55 f = file('stimuli.txt') 54 return syncopation
56 #f = file('stimuli_34only.txt')
57 55
58 #Calculate syncopation for each rhythm pattern
59 while True:
60 line = f.readline().split(';')
61 if len(line) == 1:
62 break
63 else:
64 sti_name = line[0]
65 rhythmString = line[1].split()
66 time_sig = line[2]
67 category = line[3]
68 bar = int(line[4])
69
70 rhythm = map(int,rhythmString[0].split(','))
71
72 print sti_name, metricalModel(rhythm, time_sig, category, bar)