comparison Syncopation models/synpy/rhythm_parser.py @ 45:6e9154fc58df

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