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