annotate Syncopation models/music_objects.py @ 24:08c298f47917

updated music objects to have a few more "to_string()" methods on the objects finished making the iitial version of the midi reading functions
author christopherh <christopher.harte@eecs.qmul.ac.uk>
date Sun, 12 Apr 2015 15:40:06 +0100
parents df1e7c378ee0
children 7a1730bbf15a
rev   line source
csong@9 1
csong@22 2 from basic_functions import ceiling, string_to_sequence, calculate_bar_ticks
csong@13 3 import parameter_setter
csong@13 4 import rhythm_parser
csong@9 5
csong@9 6 class Note():
csong@22 7 def __init__(self, firstarg = None, duration = None, velocity = None):
csong@22 8 self.startTime = 0
csong@22 9 self.duration = 0
csong@22 10 self.velocity = 0
csong@22 11
csong@22 12 if firstarg != None:
csong@22 13 if isinstance(firstarg,basestring):
csong@22 14 intlist = string_to_sequence(firstarg)
csong@22 15 self.startTime = intlist[0]
csong@22 16 self.duration = intlist[1]
csong@22 17 self.velocity = intlist[2]
csong@22 18 elif isinstance(firstarg,int):
csong@22 19 self.startTime = firstarg
csong@22 20
csong@22 21 if duration != None:
csong@22 22 self.duration = duration
csong@22 23 if velocity != None:
csong@22 24 self.velocity = velocity
csong@22 25
csong@22 26
csong@22 27 def to_string(self):
csong@22 28 return "(%d,%d,%f)" %(self.startTime, self.duration, self.velocity)
csong@22 29
csong@9 30
csong@9 31 # NoteSequence is a list of Note
csong@9 32 class NoteSequence(list):
csong@22 33 def __init__(self, noteSequenceString = None):
csong@22 34 if noteSequenceString != None:
csong@9 35 self.string_to_note_sequence(noteSequenceString)
csong@9 36
csong@9 37 def string_to_note_sequence(self, noteSequenceString):
csong@13 38 noteSequenceString = rhythm_parser.discardSpaces(noteSequenceString)
csong@9 39 # try:
csong@9 40 # Turning "(1,2,3),(4,5,6),(7,8,9)" into ["1,2,3","4,5,6,","7,8,9"]
csong@9 41 listStrings = noteSequenceString[1:-1].split("),(")
csong@9 42 for localString in listStrings:
csong@9 43 self.append(Note(localString))
csong@9 44
csong@22 45 def to_string(self):
csong@22 46 noteSequenceString = ""
csong@22 47 for note in self:
csong@22 48 noteSequenceString += note.to_string() + ","
csong@22 49 return noteSequenceString[:-1]
csong@9 50
csong@22 51 # VelocitySequence is a list of float numbers
csong@22 52 class VelocitySequence(list):
csong@22 53 def __init__(self, velocitySequenceString = None):
csong@22 54 if velocitySequenceString != None:
csong@22 55 self.string_to_velocity_sequence(velocitySequenceString)
csong@9 56
csong@22 57 def string_to_velocity_sequence(self,inputString):
csong@22 58 self.extend(string_to_sequence(inputString))
csong@9 59
csong@22 60 def to_string(self):
csong@22 61 return str(self)[1:-1].replace(" ","")
csong@22 62
csong@22 63
csong@23 64 def velocity_sequence_to_note_sequence(velocitySequence, nextbarVelocitySequence = None):
csong@22 65
csong@22 66 noteSequence = NoteSequence()
csong@22 67
csong@22 68 for index in range(len(velocitySequence)):
csong@22 69 if (velocitySequence[index]!= 0): # onset detected
csong@22 70 startTime = index
csong@22 71 velocity = velocitySequence[index]
csong@22 72
csong@22 73 # if there are previous notes added
csong@22 74 if( len(noteSequence) > 0):
csong@22 75 previousNote = noteSequence[-1]
csong@22 76 previousNote.duration = startTime - previousNote.startTime
csong@22 77
csong@22 78 # add the current note into note sequence
csong@22 79 noteSequence.append( Note(startTime, 0, velocity) )
csong@22 80
csong@22 81 # to set the duration for the last note
csong@22 82 if( len(noteSequence) > 0):
csong@23 83 lastNote = noteSequence[-1]
csong@23 84
csong@23 85 if nextbarVelocitySequence == None:
csong@23 86 lastNote.duration = len(velocitySequence) - lastNote.startTime
csong@23 87 else:
csong@23 88 nextNoteStartTime = next((index for index, v in enumerate(nextbarVelocitySequence) if v), None)
csong@23 89 lastNote.duration = len(velocitySequence) + nextNoteStartTime-lastNote.startTime
csong@23 90
csong@22 91
csong@22 92 return noteSequence
csong@22 93
csong@22 94
csong@22 95 def note_sequence_to_velocity_sequence(noteSequence, timespanTicks = None):
csong@22 96
csong@22 97 velocitySequence = VelocitySequence()
csong@22 98
csong@22 99 previousNoteStartTime = -1
csong@22 100
csong@22 101 for note in noteSequence:
csong@22 102
csong@22 103 interOnsetInterval = note.startTime - previousNoteStartTime
csong@22 104 velocitySequence += [0]*(interOnsetInterval-1)
csong@22 105 velocitySequence += [note.velocity]
csong@22 106
csong@22 107 previousNoteStartTime = note.startTime
csong@22 108
csong@22 109 if timespanTicks!=None:
csong@22 110 velocitySequence += [0]*(timespanTicks - len(velocitySequence))
csong@22 111 else:
csong@22 112 velocitySequence += [0]*(noteSequence[-1].duration-1)
csong@22 113
csong@22 114 # normalising velocity sequence between 0-1
csong@22 115 velocitySequence = [float(v)/max(velocitySequence) for v in velocitySequence]
csong@22 116
csong@22 117 return velocitySequence
csong@9 118
csong@9 119
csong@9 120 class BarList(list):
csong@9 121 def append(self,bar):
csong@9 122 if(len(self)>0):
csong@9 123 bar.set_previous_bar(self[-1])
csong@9 124 self[-1].set_next_bar(bar)
csong@9 125 super(BarList, self).append(bar)
csong@9 126
csong@9 127
csong@9 128 class Bar:
csong@9 129 def __init__(self, rhythmSequence, timeSignature, ticksPerQuarter=None, qpmTempo=None, nextBar=None, prevBar=None):
csong@9 130 if isinstance(rhythmSequence, NoteSequence):
csong@9 131 self.noteSequence = rhythmSequence
csong@9 132 self.velocitySequence = None
csong@9 133 elif isinstance(rhythmSequence, VelocitySequence):
csong@9 134 self.velocitySequence = rhythmSequence
csong@9 135 self.noteSequence = None
csong@9 136
csong@9 137 self.tpq = ticksPerQuarter
csong@9 138 self.qpm = qpmTempo
christopher@24 139 self.timeSignature = timeSignature
csong@9 140 self.nextBar = nextBar
csong@9 141 self.prevBar = prevBar
csong@9 142
csong@9 143 def get_note_sequence(self):
csong@22 144 if self.noteSequence == None:
csong@23 145 nextbarVelocitySequence = None
csong@23 146 if self.nextBar != None:
csong@23 147 nextbarVelocitySequence = self.nextBar.get_velocity_sequence()
csong@23 148 self.noteSequence = velocity_sequence_to_note_sequence(self.velocitySequence, nextbarVelocitySequence)
csong@9 149 return self.noteSequence
csong@9 150
csong@9 151 def get_velocity_sequence(self):
csong@22 152 if self.velocitySequence == None:
csong@23 153 self.velocitySequence = note_sequence_to_velocity_sequence(self.noteSequence)
csong@9 154 return self.velocitySequence
csong@9 155
csong@9 156 def get_binary_sequence(self):
csong@9 157 return ceiling(self.get_velocity_sequence())
csong@9 158
csong@9 159 def get_next_bar(self):
csong@9 160 return self.nextBar
csong@9 161
csong@9 162 def get_previous_bar(self):
csong@9 163 return self.prevBar
csong@9 164
csong@9 165 def set_next_bar(self, bar):
csong@9 166 self.nextBar = bar
csong@9 167
csong@9 168 def set_previous_bar(self, bar):
csong@9 169 self.prevBar = bar
csong@9 170
csong@9 171 def get_subdivision_sequence(self):
csong@18 172 return self.timeSignature.get_subdivision_sequence()
csong@9 173
csong@9 174 def get_beat_level(self):
csong@20 175 return self.timeSignature.get_beat_level()
csong@9 176
csong@9 177 def get_time_signature(self):
csong@9 178 return self.timeSignature
csong@9 179
csong@21 180 # return the length of a bar in time units (ticks)
csong@22 181 def get_bar_ticks(self):
csong@23 182 return calculate_bar_ticks(self.timeSignature.get_numerator(),self.timeSignature.get_denominator(), self.tpq)
csong@22 183
csong@9 184
csong@18 185 class TimeSignature():
csong@18 186 def __init__(self, inputString):
csong@20 187 if inputString in parameter_setter.read_time_signature():
csong@18 188 self.tsString = inputString
csong@18 189 else:
csong@18 190 print "Error: undefined time-signature ", inputString
csong@18 191 raise NullTimeSignatureError
csong@18 192
csong@18 193 def get_subdivision_sequence(self):
csong@20 194 return parameter_setter.timeSignatureBase[self.tsString][0]
csong@18 195
csong@18 196 def get_beat_level(self):
csong@20 197 return parameter_setter.timeSignatureBase[self.tsString][1]
csong@18 198
csong@18 199 def get_numerator(self):
csong@18 200 return int(self.tsString.split('/')[0])
csong@18 201
csong@18 202 def get_denominator(self):
csong@18 203 return int(self.tsString.split('/')[1])
csong@18 204
christopher@24 205 def to_string(self):
christopher@24 206 return self.tsString
csong@18 207
csong@18 208