Mercurial > hg > syncopation-dataset
view Syncopation models/music_objects.py @ 23:df1e7c378ee0
fixed KTH, and WNBD
author | csong <csong@eecs.qmul.ac.uk> |
---|---|
date | Sun, 12 Apr 2015 13:06:17 +0100 |
parents | 2dbc09ca8013 |
children | 08c298f47917 |
line wrap: on
line source
from basic_functions import ceiling, string_to_sequence, calculate_bar_ticks import parameter_setter import rhythm_parser class Note(): def __init__(self, firstarg = None, duration = None, velocity = None): self.startTime = 0 self.duration = 0 self.velocity = 0 if firstarg != None: if isinstance(firstarg,basestring): intlist = string_to_sequence(firstarg) self.startTime = intlist[0] self.duration = intlist[1] self.velocity = intlist[2] elif isinstance(firstarg,int): self.startTime = firstarg if duration != None: self.duration = duration if velocity != None: self.velocity = velocity def to_string(self): return "(%d,%d,%f)" %(self.startTime, self.duration, self.velocity) # NoteSequence is a list of Note class NoteSequence(list): def __init__(self, noteSequenceString = None): if noteSequenceString != None: self.string_to_note_sequence(noteSequenceString) def string_to_note_sequence(self, noteSequenceString): noteSequenceString = rhythm_parser.discardSpaces(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("),(") for localString in listStrings: self.append(Note(localString)) def to_string(self): noteSequenceString = "" for note in self: noteSequenceString += note.to_string() + "," return noteSequenceString[:-1] # 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 string_to_velocity_sequence(self,inputString): self.extend(string_to_sequence(inputString)) def to_string(self): return str(self)[1:-1].replace(" ","") def velocity_sequence_to_note_sequence(velocitySequence, nextbarVelocitySequence = None): noteSequence = NoteSequence() for index in range(len(velocitySequence)): if (velocitySequence[index]!= 0): # onset detected startTime = index velocity = velocitySequence[index] # if there are previous notes added if( len(noteSequence) > 0): previousNote = noteSequence[-1] previousNote.duration = startTime - previousNote.startTime # add the current note into note sequence noteSequence.append( Note(startTime, 0, velocity) ) # to set the duration for the last note if( len(noteSequence) > 0): lastNote = noteSequence[-1] if nextbarVelocitySequence == None: lastNote.duration = len(velocitySequence) - lastNote.startTime else: nextNoteStartTime = next((index for index, v in enumerate(nextbarVelocitySequence) if v), None) lastNote.duration = len(velocitySequence) + nextNoteStartTime-lastNote.startTime return noteSequence def note_sequence_to_velocity_sequence(noteSequence, timespanTicks = None): velocitySequence = VelocitySequence() previousNoteStartTime = -1 for note in noteSequence: interOnsetInterval = note.startTime - previousNoteStartTime velocitySequence += [0]*(interOnsetInterval-1) velocitySequence += [note.velocity] previousNoteStartTime = note.startTime if timespanTicks!=None: velocitySequence += [0]*(timespanTicks - len(velocitySequence)) else: velocitySequence += [0]*(noteSequence[-1].duration-1) # normalising velocity sequence between 0-1 velocitySequence = [float(v)/max(velocitySequence) for v in velocitySequence] return velocitySequence class BarList(list): def append(self,bar): if(len(self)>0): bar.set_previous_bar(self[-1]) self[-1].set_next_bar(bar) super(BarList, self).append(bar) class Bar: def __init__(self, rhythmSequence, timeSignature, ticksPerQuarter=None, qpmTempo=None, nextBar=None, prevBar=None): if isinstance(rhythmSequence, NoteSequence): self.noteSequence = rhythmSequence self.velocitySequence = None elif isinstance(rhythmSequence, VelocitySequence): self.velocitySequence = rhythmSequence self.noteSequence = None self.tpq = ticksPerQuarter self.qpm = qpmTempo self.timeSignature = TimeSignature(timeSignature) self.nextBar = nextBar self.prevBar = prevBar def get_note_sequence(self): if self.noteSequence == None: nextbarVelocitySequence = None if self.nextBar != None: nextbarVelocitySequence = self.nextBar.get_velocity_sequence() self.noteSequence = velocity_sequence_to_note_sequence(self.velocitySequence, nextbarVelocitySequence) return self.noteSequence def get_velocity_sequence(self): if self.velocitySequence == None: self.velocitySequence = note_sequence_to_velocity_sequence(self.noteSequence) return self.velocitySequence def get_binary_sequence(self): return ceiling(self.get_velocity_sequence()) def get_next_bar(self): return self.nextBar def get_previous_bar(self): return self.prevBar def set_next_bar(self, bar): self.nextBar = bar def set_previous_bar(self, bar): self.prevBar = bar def get_subdivision_sequence(self): return self.timeSignature.get_subdivision_sequence() def get_beat_level(self): return self.timeSignature.get_beat_level() def get_time_signature(self): return self.timeSignature # return the length of a bar in time units (ticks) def get_bar_ticks(self): return calculate_bar_ticks(self.timeSignature.get_numerator(),self.timeSignature.get_denominator(), self.tpq) class TimeSignature(): def __init__(self, inputString): if inputString in parameter_setter.read_time_signature(): self.tsString = inputString else: print "Error: undefined time-signature ", inputString raise NullTimeSignatureError def get_subdivision_sequence(self): return parameter_setter.timeSignatureBase[self.tsString][0] def get_beat_level(self): return parameter_setter.timeSignatureBase[self.tsString][1] def get_numerator(self): return int(self.tsString.split('/')[0]) def get_denominator(self): return int(self.tsString.split('/')[1])