Mercurial > hg > syncopation-dataset
changeset 40:6371e8f21f7d
updating the syncopation functions to fix a few problems
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Thu, 23 Apr 2015 15:46:58 +0100 |
parents | cc38b3047ed9 |
children | 903aec3d5b9f |
files | SMC2015latex/syncopation_toolkit.tex Syncopation models/basic_functions.py Syncopation models/music_objects.py Syncopation models/rhythm_parser.py Syncopation models/syncopation.py |
diffstat | 5 files changed, 94 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/SMC2015latex/syncopation_toolkit.tex Mon Apr 13 23:06:49 2015 +0100 +++ b/SMC2015latex/syncopation_toolkit.tex Thu Apr 23 15:46:58 2015 +0100 @@ -191,6 +191,47 @@ \label{ta:BNF} \end{table*} + +\begin{table} +\footnotesize{ +\begin{minted}[frame=single,framesep=10pt]{python} +T{4/4} # time signature +TPQ{4} # ticks per quarternote +# Bar 1 +Y{(0,3,2),(3,1,1),(6,2,2),(10,2,1),(12,4,1)} +# Bar 2 +V{1,0,0,0.5,0,0,1,0,0,0,0.5,0,0.5,0,0,0} +\end{minted} +} +\caption{Example rhythm annotation file containing two bars of the Son Clave rhythm. The first is expressed as a note sequence with resolution of four ticks per quarternote; the second is the same rhythm expressed as a velocity sequence.} +\label{ta:clave} +\end{table} + + +\begin{table} +\footnotesize{ +\begin{minted}[frame=single,framesep=10pt]{python} +>>>from syncopation import * +>>>import PRS as model +>>>calculate_syncopation(model, "clave.rhy") +{'bars_with_valid_output': [0, 1], + 'mean_syncopation_per_bar': 8.625, + 'model_name': 'PRS', + 'number_of_bars': 2, + 'number_of_bars_not_measured': 0, + 'source': 'clave.rhy', + 'summed_syncopation': 17.25, + 'syncopation_by_bar': [8.625, 8.625]} +\end{minted} +} +\caption{Syntax of rhythm text format Backus-Naur Form} +\label{ta:clave} +\end{table} + + + + + % \section{Page size and format}\label{sec:page_size} % \begin{equation}
--- a/Syncopation models/basic_functions.py Mon Apr 13 23:06:49 2015 +0100 +++ b/Syncopation models/basic_functions.py Thu Apr 23 15:46:58 2015 +0100 @@ -182,8 +182,8 @@ return rhythmCategory -def string_to_sequence(inputString): - return map(int, inputString.split(',')) +def string_to_sequence(inputString,typeFunction=float): + return map(typeFunction, inputString.split(',')) # # The get_subdivision_seq function returns the subdivision sequence of several common time-signatures defined by GTTM, # # or ask for the top three level of subdivision_seq manually set by the user.
--- a/Syncopation models/music_objects.py Mon Apr 13 23:06:49 2015 +0100 +++ b/Syncopation models/music_objects.py Thu Apr 23 15:46:58 2015 +0100 @@ -11,7 +11,7 @@ if firstarg != None: if isinstance(firstarg,basestring): - intlist = string_to_sequence(firstarg) + intlist = string_to_sequence(firstarg,int) self.startTime = intlist[0] self.duration = intlist[1] self.velocity = intlist[2] @@ -48,6 +48,13 @@ noteSequenceString += note.to_string() + "," return noteSequenceString[:-1] + +class NormalisedVelocityValueOutOfRange(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + # VelocitySequence is a list of float numbers class VelocitySequence(list): def __init__(self, velocitySequence = None): @@ -58,7 +65,16 @@ self+=velocitySequence def string_to_velocity_sequence(self,inputString): - self.extend(string_to_sequence(inputString)) + + def convert_velocity_value(argstring): + value = float(argstring) + if value>=0 and value<=1: + return value + else: + raise NormalisedVelocityValueOutOfRange("Value: "+argstring+" in " + inputString) + + self.extend(string_to_sequence(inputString,convert_velocity_value)) + def to_string(self): return str(velocity_sequence_to_min_timespan(self))[1:-1].replace(" ","") @@ -96,7 +112,7 @@ def note_sequence_to_velocity_sequence(noteSequence, timespanTicks = None): - + velocitySequence = VelocitySequence() previousNoteStartTime = -1
--- a/Syncopation models/rhythm_parser.py Mon Apr 13 23:06:49 2015 +0100 +++ b/Syncopation models/rhythm_parser.py Thu Apr 23 15:46:58 2015 +0100 @@ -20,6 +20,11 @@ line = line.replace(" ", '').replace("\t", '') return line +def discard_linereturns(line): + line = line.replace("\n","").replace("\r","") + return line + + # def extractInfo(line): # try: # if '{' not in line and '}' not in line: @@ -54,7 +59,7 @@ # if there is a valid field, it should be a time signature if field!=None: [fieldname,value] = field - if fieldname=="t": + if fieldname.lower()=="t": timeSignature = TimeSignature(value) else: print 'Error, first field in the file should set the time signature.' @@ -76,8 +81,8 @@ 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","") + #strip the line of line returns, spaces and comments + line = discard_linereturns(discard_spaces(discard_comments(line))) bars = BarList() @@ -116,6 +121,11 @@ return bars, tempo, timeSignature, ticksPerQuarter +class RhythmSyntaxError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) def get_next_field(line): index = line.find("}") @@ -126,7 +136,7 @@ field = fieldtext.split("{") else: print 'Error, incorrect syntax: "'+line+'"' - #raise RhythmSyntaxError(line) + raise RhythmSyntaxError(line) return field,line
--- a/Syncopation models/syncopation.py Mon Apr 13 23:06:49 2015 +0100 +++ b/Syncopation models/syncopation.py Thu Apr 23 15:46:58 2015 +0100 @@ -10,7 +10,7 @@ def sync_perbar_permodel (model, bar, parameters=None): return model.get_syncopation(bar, parameters) -def syncopation_barlist_permodel(model, source, parameters=None): +def calculate_syncopation(model, source, parameters=None): total = 0.0 barResults = [] numberOfNotes = 0 @@ -20,6 +20,9 @@ if isinstance(source, BarList): barlist = source sourceType = "bar list" + elif isinstance(source, Bar): + barlist = BarList().append(source) + sourceType = "single bar" elif isinstance(source, basestring): #treat source as a filename sourceType = source @@ -37,6 +40,8 @@ print "Error in syncopation_barlist_permodel(): unrecognised source type." barsDiscarded=0 + discardedlist = [] + includedlist = [] if barlist!=None: for bar in barlist: @@ -50,8 +55,10 @@ if barSyncopation != None: total += barSyncopation numberOfNotes += sum(bar.get_binary_sequence()) + includedlist.append(barlist.index(bar)) else: barsDiscarded += 1 + discardedlist.append(barlist.index(bar)) print 'Model could not measure bar %d, returning None.' % barlist.index(bar) import WNBD @@ -60,7 +67,16 @@ average = total / (len(barResults)-barsDiscarded) - return {"summed_syncopation":total, "average_syncopation_per_bar":average, "source":sourceType, "number_of_bars":len(barResults), "number_of_bars_not_measured":barsDiscarded, "syncopation_by_bar":barResults} + return { + "model_name":model.__name__ , + "summed_syncopation":total, + "mean_syncopation_per_bar":average, + "source":sourceType, + "number_of_bars":len(barResults), + "number_of_bars_not_measured":barsDiscarded, + "bars_with_valid_output":includedlist, + "syncopation_by_bar":barResults + }