comparison Syncopation models/synpy/music_objects.py @ 45:6e9154fc58df

moving the code files to the synpy package directory
author christopherh <christopher.harte@eecs.qmul.ac.uk>
date Thu, 23 Apr 2015 23:52:04 +0100
parents
children e71028851131
comparison
equal deleted inserted replaced
44:144460f34b5e 45:6e9154fc58df
1
2 from basic_functions import ceiling, string_to_sequence, calculate_bar_ticks, velocity_sequence_to_min_timespan
3 import parameter_setter
4 import rhythm_parser
5
6 class Note():
7 def __init__(self, firstarg = None, duration = None, velocity = None):
8 self.startTime = 0
9 self.duration = 0
10 self.velocity = 0
11
12 if firstarg != None:
13 if isinstance(firstarg,basestring):
14 intlist = string_to_sequence(firstarg,int)
15 self.startTime = intlist[0]
16 self.duration = intlist[1]
17 self.velocity = intlist[2]
18 elif isinstance(firstarg,int):
19 self.startTime = firstarg
20
21 if duration != None:
22 self.duration = duration
23 if velocity != None:
24 self.velocity = velocity
25
26
27 def to_string(self):
28 return "(%d,%d,%f)" %(self.startTime, self.duration, self.velocity)
29
30
31 # NoteSequence is a list of Note
32 class NoteSequence(list):
33 def __init__(self, noteSequenceString = None):
34 if noteSequenceString != None:
35 self.string_to_note_sequence(noteSequenceString)
36
37 def string_to_note_sequence(self, noteSequenceString):
38 noteSequenceString = rhythm_parser.discard_spaces(noteSequenceString)
39 # try:
40 # Turning "(1,2,3),(4,5,6),(7,8,9)" into ["1,2,3","4,5,6,","7,8,9"]
41 listStrings = noteSequenceString[1:-1].split("),(")
42 for localString in listStrings:
43 self.append(Note(localString))
44
45 def to_string(self):
46 noteSequenceString = ""
47 for note in self:
48 noteSequenceString += note.to_string() + ","
49 return noteSequenceString[:-1]
50
51
52 class NormalisedVelocityValueOutOfRange(Exception):
53 def __init__(self, value):
54 self.value = value
55 def __str__(self):
56 return repr(self.value)
57
58 # VelocitySequence is a list of float numbers
59 class VelocitySequence(list):
60 def __init__(self, velocitySequence = None):
61 if velocitySequence != None:
62 if isinstance(velocitySequence,basestring):
63 self.string_to_velocity_sequence(velocitySequence)
64 elif isinstance(velocitySequence, list):
65 self+=velocitySequence
66
67 def string_to_velocity_sequence(self,inputString):
68
69 def convert_velocity_value(argstring):
70 value = float(argstring)
71 if value>=0 and value<=1:
72 return value
73 else:
74 raise NormalisedVelocityValueOutOfRange("Value: "+argstring+" in " + inputString)
75
76 self.extend(string_to_sequence(inputString,convert_velocity_value))
77
78
79 def to_string(self):
80 return str(velocity_sequence_to_min_timespan(self))[1:-1].replace(" ","")
81
82
83 def velocity_sequence_to_note_sequence(velocitySequence, nextbarVelocitySequence = None):
84
85 noteSequence = NoteSequence()
86
87 for index in range(len(velocitySequence)):
88 if (velocitySequence[index]!= 0): # onset detected
89 startTime = index
90 velocity = velocitySequence[index]
91
92 # if there are previous notes added
93 if( len(noteSequence) > 0):
94 previousNote = noteSequence[-1]
95 previousNote.duration = startTime - previousNote.startTime
96
97 # add the current note into note sequence
98 noteSequence.append( Note(startTime, 0, velocity) )
99
100 # to set the duration for the last note
101 if( len(noteSequence) > 0):
102 lastNote = noteSequence[-1]
103
104 if nextbarVelocitySequence == None:
105 lastNote.duration = len(velocitySequence) - lastNote.startTime
106 else:
107 nextNoteStartTime = next((index for index, v in enumerate(nextbarVelocitySequence) if v), None)
108 lastNote.duration = len(velocitySequence) + nextNoteStartTime-lastNote.startTime
109
110
111 return noteSequence
112
113
114 def note_sequence_to_velocity_sequence(noteSequence, timespanTicks = None):
115
116 velocitySequence = VelocitySequence()
117
118 previousNoteStartTime = -1
119
120 for note in noteSequence:
121
122 interOnsetInterval = note.startTime - previousNoteStartTime
123 velocitySequence += [0]*(interOnsetInterval-1)
124 velocitySequence += [note.velocity]
125
126 previousNoteStartTime = note.startTime
127
128 if timespanTicks!=None:
129 velocitySequence += [0]*(timespanTicks - len(velocitySequence))
130 else:
131 velocitySequence += [0]*(noteSequence[-1].duration-1)
132
133 # normalising velocity sequence between 0-1
134 if max(velocitySequence)>0:
135 velocitySequence = VelocitySequence([float(v)/max(velocitySequence) for v in velocitySequence])
136
137 return velocitySequence
138
139
140 class BarList(list):
141 def append(self,bar):
142 if(len(self)>0):
143 bar.set_previous_bar(self[-1])
144 self[-1].set_next_bar(bar)
145 super(BarList, self).append(bar)
146
147 def concat(self, barList):
148 while(len(barList)!=0):
149 localbar = barList[0]
150 self.append(localbar)
151 barList.remove(localbar)
152
153
154 class Bar:
155 def __init__(self, rhythmSequence, timeSignature, ticksPerQuarter=None, qpmTempo=None, nextBar=None, prevBar=None):
156 if isinstance(rhythmSequence, NoteSequence):
157 self.noteSequence = rhythmSequence
158 self.velocitySequence = None
159 elif isinstance(rhythmSequence, VelocitySequence):
160 self.velocitySequence = rhythmSequence
161 self.noteSequence = None
162
163 self.tpq = ticksPerQuarter
164 self.qpm = qpmTempo
165 if isinstance(timeSignature, basestring):
166 self.timeSignature = TimeSignature(timeSignature)
167 else:
168 self.timeSignature = timeSignature
169 self.nextBar = nextBar
170 self.prevBar = prevBar
171
172 def get_note_sequence(self):
173 if self.noteSequence == None:
174 nextbarVelocitySequence = None
175 if self.nextBar != None:
176 nextbarVelocitySequence = self.nextBar.get_velocity_sequence()
177 self.noteSequence = velocity_sequence_to_note_sequence(self.velocitySequence, nextbarVelocitySequence)
178 return self.noteSequence
179
180 def get_velocity_sequence(self):
181 if self.velocitySequence == None:
182 self.velocitySequence = note_sequence_to_velocity_sequence(self.noteSequence, self.get_bar_ticks())
183 return self.velocitySequence
184
185 def get_binary_sequence(self):
186 return ceiling(self.get_velocity_sequence())
187
188 def get_next_bar(self):
189 return self.nextBar
190
191 def get_previous_bar(self):
192 return self.prevBar
193
194 def set_next_bar(self, bar):
195 self.nextBar = bar
196
197 def set_previous_bar(self, bar):
198 self.prevBar = bar
199
200 def get_subdivision_sequence(self):
201 return self.timeSignature.get_subdivision_sequence()
202
203 def get_beat_level(self):
204 return self.timeSignature.get_beat_level()
205
206 def get_time_signature(self):
207 return self.timeSignature
208
209 # return the length of a bar in time units (ticks)
210 def get_bar_ticks(self):
211 return calculate_bar_ticks(self.timeSignature.get_numerator(),self.timeSignature.get_denominator(), self.tpq)
212
213 def is_empty(self):
214 if max(self.get_velocity_sequence())>0:
215 return False
216 else:
217 return True
218
219 def to_string(self, sequenceType=None):
220 output = "t{"+self.timeSignature.to_string()+"}"
221 prev = self.get_previous_bar()
222 if prev!=None:
223 if prev.get_time_signature()==self.get_time_signature():
224 output=""
225
226 if sequenceType==None or sequenceType=="v":
227 output += "v{"+self.get_velocity_sequence().to_string()+"}"
228 else:
229 output += "y{"+self.get_note_sequence().to_string()+"}"
230 return output
231
232
233 class TimeSignature():
234 def __init__(self, inputString):
235 if inputString in parameter_setter.read_time_signature():
236 self.tsString = inputString
237 else:
238 print "Error: undefined time-signature: ", inputString
239 raise NullTimeSignatureError
240
241 def get_subdivision_sequence(self):
242 return parameter_setter.timeSignatureBase[self.tsString][0]
243
244 def get_beat_level(self):
245 return parameter_setter.timeSignatureBase[self.tsString][1]
246
247 def get_numerator(self):
248 return int(self.tsString.split('/')[0])
249
250 def get_denominator(self):
251 return int(self.tsString.split('/')[1])
252
253 def to_string(self):
254 return self.tsString
255
256