Mercurial > hg > syncopation-dataset
changeset 29:7a1730bbf15a
updating files with new text reading code
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Sun, 12 Apr 2015 22:37:56 +0100 |
parents | 5de1cb45c145 |
children | d9ac6e0d1daf |
files | Syncopation models/basic_functions.py Syncopation models/music_objects.py Syncopation models/rhythm_parser.py Syncopation models/rhythmbase/clave.txt Syncopation models/text_bnf_syntax.txt |
diffstat | 5 files changed, 144 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/Syncopation models/basic_functions.py Sun Apr 12 22:34:35 2015 +0100 +++ b/Syncopation models/basic_functions.py Sun Apr 12 22:37:56 2015 +0100 @@ -94,6 +94,7 @@ # convert a velocity sequence to its minimum time-span representation def velocity_sequence_to_min_timespan(velocitySequence): + from music_objects import VelocitySequence minTimeSpanVelocitySeq = [1] for divisors in find_divisor(len(velocitySequence)): segments = subdivide(velocitySequence,divisors) @@ -103,8 +104,9 @@ minTimeSpanVelocitySeq.append(s[0]) if sum(minTimeSpanVelocitySeq) == sum(velocitySequence): break - return minTimeSpanVelocitySeq + return VelocitySequence(minTimeSpanVelocitySeq) +""" # convert a note sequence to its minimum time-span representation def note_sequence_to_min_timespan(noteSequence): from music_objects import note_sequence_to_velocity_sequence @@ -129,7 +131,7 @@ note.duration = note.duration/delta_t return noteSequence - +""" # get_note_indices returns all the indices of all the notes in this velocity_sequence def get_note_indices(velocitySequence):
--- a/Syncopation models/music_objects.py Sun Apr 12 22:34:35 2015 +0100 +++ b/Syncopation models/music_objects.py Sun Apr 12 22:37:56 2015 +0100 @@ -1,5 +1,5 @@ -from basic_functions import ceiling, string_to_sequence, calculate_bar_ticks +from basic_functions import ceiling, string_to_sequence, calculate_bar_ticks, velocity_sequence_to_min_timespan import parameter_setter import rhythm_parser @@ -35,7 +35,7 @@ self.string_to_note_sequence(noteSequenceString) def string_to_note_sequence(self, noteSequenceString): - noteSequenceString = rhythm_parser.discardSpaces(noteSequenceString) + noteSequenceString = rhythm_parser.discard_spaces(noteSequenceString) # try: # Turning "(1,2,3),(4,5,6),(7,8,9)" into ["1,2,3","4,5,6,","7,8,9"] listStrings = noteSequenceString[1:-1].split("),(") @@ -50,15 +50,18 @@ # VelocitySequence is a list of float numbers class VelocitySequence(list): - def __init__(self, velocitySequenceString = None): - if velocitySequenceString != None: - self.string_to_velocity_sequence(velocitySequenceString) + def __init__(self, velocitySequence = None): + if velocitySequence != None: + if isinstance(velocitySequence,basestring): + self.string_to_velocity_sequence(velocitySequence) + elif isinstance(velocitySequence, list): + self+=velocitySequence def string_to_velocity_sequence(self,inputString): self.extend(string_to_sequence(inputString)) def to_string(self): - return str(self)[1:-1].replace(" ","") + return str(velocity_sequence_to_min_timespan(self))[1:-1].replace(" ","") def velocity_sequence_to_note_sequence(velocitySequence, nextbarVelocitySequence = None): @@ -112,7 +115,7 @@ velocitySequence += [0]*(noteSequence[-1].duration-1) # normalising velocity sequence between 0-1 - velocitySequence = [float(v)/max(velocitySequence) for v in velocitySequence] + velocitySequence = VelocitySequence([float(v)/max(velocitySequence) for v in velocitySequence]) return velocitySequence @@ -124,6 +127,12 @@ self[-1].set_next_bar(bar) super(BarList, self).append(bar) + def concat(self, barList): + while(len(barList)!=0): + localbar = barList[0] + self.append(localbar) + barList.remove(localbar) + class Bar: def __init__(self, rhythmSequence, timeSignature, ticksPerQuarter=None, qpmTempo=None, nextBar=None, prevBar=None): @@ -181,6 +190,13 @@ def get_bar_ticks(self): return calculate_bar_ticks(self.timeSignature.get_numerator(),self.timeSignature.get_denominator(), self.tpq) + def to_string(self, sequenceType=None): + if sequenceType==None or sequenceType=="v": + output = "v{"+self.get_velocity_sequence().to_string()+"}" + else: + output = "y{"+self.get_note_sequence().to_string()+"}" + return output + class TimeSignature(): def __init__(self, inputString):
--- a/Syncopation models/rhythm_parser.py Sun Apr 12 22:34:35 2015 +0100 +++ b/Syncopation models/rhythm_parser.py Sun Apr 12 22:37:56 2015 +0100 @@ -4,18 +4,18 @@ ''' # Parse the rhythm file and return a list of Bar objects -Piece = [] +#Piece = [] from parameter_setter import timeSignatureBase - +from music_objects import * comment_sign = '#' -def discardComments(line): +def discard_comments(line): if comment_sign in line: line = line[0:line.find(comment_sign)] return line -def discardSpaces(line): +def discard_spaces(line): line = line.replace(" ", '').replace("\t", '') return line @@ -29,78 +29,108 @@ print 'Rhythmic information needs to be enclosed by "{" and "}"' -current_timesig = '' -current_timesigValue = [] -def process(line): - try: - if 't' in line: - current_timesig = extractInfo(line) - if current_timesig in timesigBase: - current_timesigValue = timesigBase[current_timesig] + +def read_rhythm(fileName): + fileContent = file(fileName) + + barList = BarList() + + tempo=None + timeSignature=None + ticksPerQuarter=None + + # for each line in the file, parse the line and add any + # new bars to the main bar list for the piece + for line in fileContent: + + # ignore the line if it's only a comment + if is_comment(line) or line=="\n": + continue + + # if time signature has not yet been set then it should be the first + # thing we find in a file after the comments at the top + if timeSignature==None: + (field, line) = get_next_field(line) + # if there is a valid field, it should be a time signature + if field!=None: + [fieldname,value] = field + if fieldname=="t": + timeSignature = TimeSignature(value) + else: + print 'Error, first field in the file should set the time signature.' + + # parse the line + (newbarlist, tempo, timeSignature, ticksPerQuarter) = parse_line(line, timeSignature, tempo, ticksPerQuarter) + + # if we found some bars in this line then add them to the overall bar list + if len(newbarlist)>0: + barList.concat(newbarlist) + + return barList + +def is_comment(line): + if discard_spaces(line)[0]=="#": + return True + else: + return False + +def parse_line(line, timeSignature=None, tempo=None, ticksPerQuarter=None): + + #strip the line of spaces and comments + line = discard_spaces(discard_comments(line)).replace("\n","") + + bars = BarList() + + #work through each field in the line + while len(line)>0: + (field, line) = get_next_field(line) + + if field!=None: + + [fieldname, value] = field + + if fieldname.lower() == "v": + #velocity sequence + bar = Bar(VelocitySequence(value),timeSignature, ticksPerQuarter, tempo) + bars.append(bar) + + elif fieldname.lower() == "y": + #note sequence + bar = Bar(NoteSequence(value), timeSignature, ticksPerQuarter, tempo) + bars.append(bar) + + elif fieldname.lower() == "t": + #time signature + timeSignature = TimeSignature(value) + + elif fieldname.lower() == "tpq": + #ticks per quarter + ticksPerQuarter = int(value) + + elif fieldname.lower() == "qpm": + #tempo + tempo = int(value) + else: - raise NoTimesigError(current_timesig) - - elif 'v' in line: - if current_timesig == '': - raise InitialTimesigError(line) - else: - rhythmString = extractInfo(line) - rhythm_seq = map(int,rhythmString.split(',')) - Piece.append(Bar(rhythm_seq, current_timesigValue[0], current_timesigValue[1])) - - else: - raise SymbolError(line) + print 'Unrecognised field type: "' + fieldname + '"' - except InitialTimesigError: - print 'The initial time-signature is not given.' - except NoTimesigError: - print 'The time-signature is not recognised.' - except SymbolError: - print 'Unrecognised symbol.' + return bars, tempo, timeSignature, ticksPerQuarter -def readRhythm(fileName): - try: - f = file(fileName) - - # Clean up each line by discarding comments and spaces; extract time-signature or sequence information - isfinished = False - while(not isfinished): - line = f.readline() - if len(line) == 0: - isfinished = True - else: - cleanline = discardSpaces(discardComments(line)) - process(cleanline) +def get_next_field(line): + index = line.find("}") + field = None + if index>=0: + fieldtext = line[:index] + line = line[index+1:] + field = fieldtext.split("{") + else: + print 'Error, incorrect syntax: "'+line+'"' + #raise RhythmSyntaxError(line) - # Extract time-signature and rhythm sequence information + return field,line - except IOError as e: - print "I/O error({0}): {1}".format(e.errno, e.strerror) - except: - print 'Unexpected error.'#, sys.exc_info()[0] -# To check the -def isInfoValid(info): - # If two parts of information is not seperated by ; - # if 't' in info and 'q' in info: - # print 'Error: time-signature and rhythm sequence needs ";" to seperate. Please check this rhythm file: %s.' %fileName - # Piece = None - # break - # elif '{' not in info and '}' not in info: - # print 'Error: information needs to be enclosed by "{ }". Please check this rhythm file: %s.' %fileName - # Piece = None - # break - # else: - return True -# To check whether the given time-signature is existed; if not then requires user to add in the new time-signature -#def checkTimesig(input): -# # TESTING -# line = 't{4/4} q{1,0,0,1,0,0,1,0,0,0,1,0,0.8,0,0,0} t{2/4} # This is a comment' -# # print discardSpaces(discardComments(line)) -# print line[line.find('{')+1:line.find('}')] -# #print readRhythm("rhythmbase/testrhythm.txt") -
--- a/Syncopation models/rhythmbase/clave.txt Sun Apr 12 22:34:35 2015 +0100 +++ b/Syncopation models/rhythmbase/clave.txt Sun Apr 12 22:37:56 2015 +0100 @@ -1,3 +1,12 @@ -t{4/4};q{1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0} -q{1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0} -t{3/4};q{1,1,1} \ No newline at end of file +#this is a comment too + +t{4/4}qpm{100}v{1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0} # this is a comment +v{1,0,0,1,0,0, 1,0,0,0,1,0, 1,0,0,0} +TPQ{1000} +t{3/4} + +#this is a comment + v{1,1,1} qpm{120} v{1,0,1,0,1,0} + + + y{(1,2,3),(3,2,3),(4,2,2)} \ No newline at end of file
--- a/Syncopation models/text_bnf_syntax.txt Sun Apr 12 22:34:35 2015 +0100 +++ b/Syncopation models/text_bnf_syntax.txt Sun Apr 12 22:37:56 2015 +0100 @@ -1,11 +1,15 @@ -<piece> ::= <timesig> <line> | <piece> <line> +<piece> ::= [<comment-lines>] <timesig> <line> | <piece> <line> + +<comment-lines> ::= <comment> "\n" | <comment-lines> <comment> "\n" <tempo> ::= "QPM{" <digits> "}" <ticks per quarter> ::= "TPQ{" <digits> "}" -<line> ::= [<barlist>] ["#" <comment-text>] "\n" +<line> ::= [<barlist>] [<comment>] "\n" + +<comment> ::= "#" <comment-text> <barlist> ::= <time-info> | [<time-info>] <bar> | <barlist> <bar>