Mercurial > hg > syncopation-dataset
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) |