csong@9
|
1 '''
|
csong@35
|
2 Authors: Chunyang Song, Christopher Harte
|
csong@9
|
3 Institution: Centre for Digital Music, Queen Mary University of London
|
csong@9
|
4 '''
|
csong@9
|
5
|
csong@9
|
6 # Parse the rhythm file and return a list of Bar objects
|
christopher@29
|
7 #Piece = []
|
csong@9
|
8
|
csong@20
|
9 from parameter_setter import timeSignatureBase
|
christopher@29
|
10 from music_objects import *
|
csong@9
|
11
|
csong@9
|
12 comment_sign = '#'
|
christopher@29
|
13 def discard_comments(line):
|
csong@9
|
14 if comment_sign in line:
|
csong@9
|
15 line = line[0:line.find(comment_sign)]
|
csong@9
|
16 return line
|
csong@9
|
17
|
christopher@29
|
18 def discard_spaces(line):
|
csong@9
|
19 line = line.replace(" ", '').replace("\t", '')
|
csong@9
|
20 return line
|
csong@9
|
21
|
csong@35
|
22 # def extractInfo(line):
|
csong@35
|
23 # try:
|
csong@35
|
24 # if '{' not in line and '}' not in line:
|
csong@35
|
25 # raise RhythmSyntaxError(line)
|
csong@35
|
26 # else:
|
csong@35
|
27 # return line[line.find('{')+1 : line.find('}')]
|
csong@35
|
28 # except RhythmSyntaxError:
|
csong@35
|
29 # print 'Rhythmic information needs to be enclosed by "{" and "}"'
|
csong@9
|
30
|
christopher@29
|
31
|
christopher@29
|
32 def read_rhythm(fileName):
|
christopher@29
|
33 fileContent = file(fileName)
|
christopher@29
|
34
|
christopher@29
|
35 barList = BarList()
|
christopher@29
|
36
|
christopher@29
|
37 tempo=None
|
christopher@29
|
38 timeSignature=None
|
christopher@29
|
39 ticksPerQuarter=None
|
christopher@29
|
40
|
christopher@29
|
41 # for each line in the file, parse the line and add any
|
christopher@29
|
42 # new bars to the main bar list for the piece
|
christopher@29
|
43 for line in fileContent:
|
christopher@29
|
44
|
christopher@29
|
45 # ignore the line if it's only a comment
|
christopher@29
|
46 if is_comment(line) or line=="\n":
|
christopher@29
|
47 continue
|
christopher@29
|
48
|
christopher@29
|
49 # if time signature has not yet been set then it should be the first
|
christopher@29
|
50 # thing we find in a file after the comments at the top
|
christopher@29
|
51 if timeSignature==None:
|
christopher@29
|
52 (field, line) = get_next_field(line)
|
christopher@29
|
53 # if there is a valid field, it should be a time signature
|
christopher@29
|
54 if field!=None:
|
christopher@29
|
55 [fieldname,value] = field
|
christopher@29
|
56 if fieldname=="t":
|
christopher@29
|
57 timeSignature = TimeSignature(value)
|
christopher@29
|
58 else:
|
christopher@29
|
59 print 'Error, first field in the file should set the time signature.'
|
christopher@29
|
60
|
christopher@29
|
61 # parse the line
|
christopher@29
|
62 (newbarlist, tempo, timeSignature, ticksPerQuarter) = parse_line(line, timeSignature, tempo, ticksPerQuarter)
|
christopher@29
|
63
|
christopher@29
|
64 # if we found some bars in this line then add them to the overall bar list
|
christopher@29
|
65 if len(newbarlist)>0:
|
christopher@29
|
66 barList.concat(newbarlist)
|
christopher@29
|
67
|
christopher@29
|
68 return barList
|
christopher@29
|
69
|
christopher@29
|
70 def is_comment(line):
|
csong@35
|
71 if discard_spaces(line)[0]==comment_sign:
|
christopher@29
|
72 return True
|
christopher@29
|
73 else:
|
christopher@29
|
74 return False
|
christopher@29
|
75
|
christopher@29
|
76 def parse_line(line, timeSignature=None, tempo=None, ticksPerQuarter=None):
|
christopher@29
|
77
|
christopher@29
|
78 #strip the line of spaces and comments
|
christopher@29
|
79 line = discard_spaces(discard_comments(line)).replace("\n","")
|
christopher@29
|
80
|
christopher@29
|
81 bars = BarList()
|
christopher@29
|
82
|
christopher@29
|
83 #work through each field in the line
|
christopher@29
|
84 while len(line)>0:
|
christopher@29
|
85 (field, line) = get_next_field(line)
|
christopher@29
|
86
|
christopher@29
|
87 if field!=None:
|
christopher@29
|
88
|
christopher@29
|
89 [fieldname, value] = field
|
christopher@29
|
90
|
christopher@29
|
91 if fieldname.lower() == "v":
|
christopher@29
|
92 #velocity sequence
|
christopher@29
|
93 bar = Bar(VelocitySequence(value),timeSignature, ticksPerQuarter, tempo)
|
christopher@29
|
94 bars.append(bar)
|
christopher@29
|
95
|
christopher@29
|
96 elif fieldname.lower() == "y":
|
christopher@29
|
97 #note sequence
|
christopher@29
|
98 bar = Bar(NoteSequence(value), timeSignature, ticksPerQuarter, tempo)
|
christopher@29
|
99 bars.append(bar)
|
christopher@29
|
100
|
christopher@29
|
101 elif fieldname.lower() == "t":
|
christopher@29
|
102 #time signature
|
christopher@29
|
103 timeSignature = TimeSignature(value)
|
christopher@29
|
104
|
christopher@29
|
105 elif fieldname.lower() == "tpq":
|
christopher@29
|
106 #ticks per quarter
|
christopher@29
|
107 ticksPerQuarter = int(value)
|
christopher@29
|
108
|
christopher@29
|
109 elif fieldname.lower() == "qpm":
|
christopher@29
|
110 #tempo
|
christopher@29
|
111 tempo = int(value)
|
christopher@29
|
112
|
csong@9
|
113 else:
|
christopher@29
|
114 print 'Unrecognised field type: "' + fieldname + '"'
|
csong@9
|
115
|
christopher@29
|
116 return bars, tempo, timeSignature, ticksPerQuarter
|
csong@9
|
117
|
csong@9
|
118
|
christopher@29
|
119 def get_next_field(line):
|
christopher@29
|
120 index = line.find("}")
|
christopher@29
|
121 field = None
|
christopher@29
|
122 if index>=0:
|
christopher@29
|
123 fieldtext = line[:index]
|
christopher@29
|
124 line = line[index+1:]
|
christopher@29
|
125 field = fieldtext.split("{")
|
christopher@29
|
126 else:
|
christopher@29
|
127 print 'Error, incorrect syntax: "'+line+'"'
|
christopher@29
|
128 #raise RhythmSyntaxError(line)
|
csong@9
|
129
|
christopher@29
|
130 return field,line
|
csong@9
|
131
|
csong@9
|
132
|
csong@9
|
133
|
csong@9
|
134
|
csong@9
|
135
|