annotate synpy/rhythm_parser.py @ 76:90b68f259541 tip

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