christopher@45
|
1 '''
|
christopher@45
|
2 Author: Chunyang Song
|
christopher@45
|
3 Institution: Centre for Digital Music, Queen Mary University of London
|
christopher@45
|
4 '''
|
christopher@45
|
5
|
christopher@45
|
6 # Set the parameters: time-signature, subdivision-sequence, strong-beat-level; Lmax; weight-sequence
|
christopher@45
|
7 # Important condition: Lmax needs to be no less than the length of subdivision-sequence and the length of weight-sequence
|
christopher@45
|
8
|
christopher@45
|
9
|
christopher@45
|
10 # {'key': time-signature} :
|
christopher@45
|
11 # {'value': [subdivision-sequence, theoretical beat-level represented by index in the subdivision-sequence list]}
|
christopher@45
|
12 timeSignatureBase = {
|
christopher@50
|
13 '2/2': [[1,2,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
14 '3/2': [[1,3,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
15 '4/2': [[1,2,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
16 '2/4': [[1,2,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
17 '3/4': [[1,3,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
18 '4/4': [[1,2,2,2,2,2,2,2,2,2,2,2,2,2],2],
|
christopher@50
|
19 '5/4': [[1,5,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
20 '7/4': [[1,7,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
21 '3/8': [[1,3,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
22 '5/8': [[1,5,2,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
23 '6/8': [[1,2,3,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
24 '9/8': [[1,3,3,2,2,2,2,2,2,2,2,2,2,2],1],
|
christopher@50
|
25 '12/8':[[1,2,2,3,2,2,2,2,2,2,2,2,2,2],2],
|
christopher@45
|
26 }
|
christopher@45
|
27
|
christopher@45
|
28
|
christopher@45
|
29 def add_time_signature(timeSignature, subdivisionSequence, beatLevel):
|
christopher@45
|
30 if is_time_signature_valid(timeSignature,subdivisionSequence,beatLevel):
|
christopher@45
|
31 if timeSignature in timesigBase:
|
christopher@45
|
32 print 'This time-signature is existed already.'
|
christopher@45
|
33 else:
|
christopher@45
|
34 timeSignatureBase[timeSignature] = [subdivisionSequence, beatLevel]
|
christopher@45
|
35 write_time_signature()
|
christopher@45
|
36
|
christopher@45
|
37 def update_time_signature(timeSignature, subdivisionSequence, beatLevel):
|
christopher@45
|
38 if is_time_signature_valid(timeSignature,subdivisionSequence,beatLevel):
|
christopher@45
|
39 if timeSignature in timeSignatureBase:
|
christopher@45
|
40 print 'Original settings for ', timeSignature, ':',timeSignatureBase[timeSignature]
|
christopher@45
|
41 timeSignatureBase[timeSignature] = [subdivisionSequence, beatLevel]
|
christopher@45
|
42 print 'Changed into:',timeSignatureBase[timeSignature]
|
christopher@45
|
43 write_time_signature()
|
christopher@45
|
44
|
christopher@45
|
45 def is_time_signature_valid(timeSignature, subdivisionSequence, beatLevel):
|
christopher@45
|
46 isValid = False
|
christopher@45
|
47 if ('/' not in timeSignature) or (not timeSignature.split('/')[0].isdigit()) or (not timeSignature.split('/')[1].isdigit()):
|
christopher@45
|
48 print 'Error: invalid time-signature. Please indicate in the form of fraction, e.g. 4/4, 6/8 or 3/4.'
|
christopher@45
|
49 elif subdivisionSequence != [s for s in subdivisionSequence if isinstance(s,int)]:
|
christopher@45
|
50 print 'Error: invalid subdivision sequence. Please indicate in the form of list of numbers, e.g [1,2,2,2,2].'
|
christopher@45
|
51 elif beatLevel >= len(subdivisionSequence):
|
christopher@45
|
52 print 'Error: beat-level exceeds the range of subdivision sequence list.'
|
christopher@45
|
53 else:
|
christopher@45
|
54 isValid = True
|
christopher@45
|
55 return isValid
|
christopher@45
|
56
|
christopher@45
|
57 def write_time_signature():
|
christopher@45
|
58 import cPickle as pickle
|
christopher@45
|
59 timeSigFile = open('TimeSignature.pkl', 'wb')
|
christopher@45
|
60 pickle.dump(timeSignatureBase, timeSigFile)
|
christopher@45
|
61 timeSigFile.close()
|
christopher@45
|
62
|
christopher@45
|
63 def read_time_signature():
|
christopher@45
|
64 import cPickle as pickle
|
christopher@45
|
65 timeSigFile = open('TimeSignature.pkl','rb')
|
christopher@45
|
66 data = pickle.load(timeSigFile)
|
christopher@45
|
67 return data
|
christopher@45
|
68 timeSigFile.close()
|
christopher@45
|
69
|
christopher@45
|
70 def print_time_signature_base():
|
christopher@45
|
71 data = read_time_signature()
|
christopher@45
|
72 for timeSignature, settings in data.items():
|
christopher@45
|
73 print timeSignature, settings
|
christopher@45
|
74
|
christopher@45
|
75
|
christopher@45
|
76 def are_parameters_valid(Lmax, weightSequence, subdivisionSequence):
|
christopher@45
|
77
|
christopher@45
|
78 # is_Lmax_valid() checks:
|
christopher@45
|
79 # 1. if Lmax is a non-negative integer
|
christopher@45
|
80 # 2. if Lmax is higher than the length of weightSequence and subdivisionSequence
|
christopher@45
|
81 def is_Lmax_valid():
|
christopher@45
|
82 isValid = False
|
christopher@45
|
83 if isinstance(Lmax,int) and Lmax > 0:
|
christopher@45
|
84 if Lmax <= len(subdivisionSequence)-1:
|
christopher@45
|
85 if Lmax <= len(weightSequence)-1:
|
christopher@45
|
86 isValid = True
|
christopher@45
|
87 else:
|
christopher@45
|
88 print 'Error: Lmax exceeds the length of weight-sequence. Either reduce Lmax, or provide a new weight-sequence whose length is greater or equal to Lmax.'
|
christopher@45
|
89 else:
|
christopher@45
|
90 print 'Error: Lmax exceeds the length of subdivision-sequence. Either reduce Lmax, or extend subdivision-sequence through updating time-signature (refer to update_time_signature function).'
|
christopher@45
|
91 else:
|
christopher@45
|
92 print 'Error: Lmax needs to be a positive integer.'
|
christopher@45
|
93 return isValid
|
christopher@45
|
94
|
christopher@45
|
95 # is_weight_sequence_valid() checks:
|
christopher@45
|
96 # 1. weightSequence is a list of numbers
|
christopher@45
|
97 # 2. the length of weightSequence is no less than Lmax
|
christopher@45
|
98 def is_weight_sequence_valid():
|
christopher@45
|
99 isValid = False
|
christopher@45
|
100 if isinstance(weightSequence,list) and weightSequence == [i for i in weightSequence if isinstance(i,int)]:
|
christopher@45
|
101 if len(weightSequence) >= Lmax:
|
christopher@45
|
102 isValid = True
|
christopher@45
|
103 else:
|
christopher@45
|
104 print 'Error: the length of weight-sequence needs to be greater or equal to Lmax.'
|
christopher@45
|
105 else:
|
christopher@45
|
106 print 'Error: the weight-sequence needs to be a list of integers.'
|
christopher@45
|
107 return isValid
|
christopher@45
|
108
|
christopher@45
|
109
|
christopher@45
|
110 if is_weight_sequence_valid() and is_Lmax_valid():
|
christopher@45
|
111 return True
|
christopher@45
|
112 else:
|
christopher@45
|
113 return False
|