Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def _play_thread(child_clock):
note_iterator = self.get_note_iterator(start_beat, stop_beat, selected_voices)
self.get_note_iterator(start_beat, stop_beat)
try:
current_note = next(note_iterator)
except StopIteration:
return
child_clock.wait(current_note.start_beat - start_beat)
while True:
assert isinstance(current_note, PerformanceNote)
if note_filter is not None:
note_filter(current_note).play(instrument, clock=child_clock, blocking=False)
else:
current_note.play(instrument, clock=child_clock, blocking=False)
try:
next_note = next(note_iterator)
child_clock.wait(next_note.start_beat - current_note.start_beat)
current_note = next_note
except StopIteration:
# when done, wait for the children to finish
child_clock.wait(current_note.length_sum())
return
if this_pitch != out[-1].pitch:
out.append(pymusicxml.GraceNote(
this_pitch, 1.0, stemless=True,
notehead=(get_xml_notehead(self.properties.noteheads[0])
if self.properties.noteheads[0] != "normal" else None)
))
self._attach_articulations_to_xml_note_group(out)
if source_id_dict is not None and self.does_glissando():
# this is where we populate the source_id_dict passed down to us from the top level "to_music_xml()" call
# sometimes a note will not have a _source_id property defined, since it never gets broken into tied
# components. However, if it's a glissando and there's stemless grace notes involved, we're going to
# have to give it a _source_id so that it can share it with its grace notes
if "_source_id" not in self.properties:
self.properties["_source_id"] = performance_module.PerformanceNote.next_id()
# here we take the new note that we're creating and add it to the bin in source_id_dict that
# contains all the notes of the same source, so that they can be joined by glissandi
if self.properties["_source_id"] in source_id_dict:
# this source_id is already associated with a leaf, so add it to the list
source_id_dict[self.properties["_source_id"]].extend(out)
else:
# we don't yet have a record on this source_id, so start a list with this object under that key
source_id_dict[self.properties["_source_id"]] = list(out)
return out
def next_id() -> int:
"""
Return a new unique ID number for this note, different from all PerformanceNotes created so far.
:return: id number (int)
"""
return next(PerformanceNote._id_generator)
def _fill_in_rests(notes, total_length):
notes_and_rests = []
t = 0
for note in notes:
if t + 1e-10 < note.start_beat:
notes_and_rests.append(performance_module.PerformanceNote(t, note.start_beat - t, None, None, {}))
notes_and_rests.append(note)
t = note.end_beat
if t < total_length:
notes_and_rests.append(performance_module.PerformanceNote(t, total_length - t, None, None, {}))
return notes_and_rests
def new_note(self, start_beat: float, length, pitch, volume, properties: dict) -> PerformanceNote:
"""
Construct and add a new PerformanceNote to this Performance
:param start_beat: the start beat of the note
:param length: length of the note in beats (either a float or a list of floats representing tied segments)
:param pitch: pitch of the note (float, Envelope, or list to interpret as an envelope)
:param volume: volume of the note (float or Envelope, or list to interpret as an envelope)
:param properties: dictionary of note properties, or string representing those properties
:return: the note just added
"""
return self.add_note(PerformanceNote(start_beat, length, pitch, volume, properties))
engraving_settings.articulation_split_protocols[articulation] == "both":
# this articulation is about the attack and release, but it doesn't really make
# sense to play it on a note the middle of a tied group
if self.properties.starts_tie() and self.properties.ends_tie():
self.properties.articulations.remove(articulation)
if second_part.properties.starts_tie() and second_part.properties.ends_tie():
second_part.properties.articulations.remove(articulation)
# note, if the split protocol says "all" (or doesn't exist), then we just
# default to keeping the articulation on everything
# we also want to keep track of which notes came from the same original note for doing ties and such
if "_source_id" in self.properties.temp:
second_part.properties.temp["_source_id"] = self.properties.temp["_source_id"]
else:
second_part.properties.temp["_source_id"] = \
self.properties.temp["_source_id"] = PerformanceNote.next_id()
return self, second_part
def split_at_beat(self, split_beat: float) -> Sequence['PerformanceNote']:
"""
Splits this note at the given beat, returning a tuple of the pieces created
:param split_beat: where to split (relative to the performance start time, not the note start time)
:return: tuple of (first half note, second half note) if split beat is within the note.
Otherwise just return the unchanged note in a length-1 tuple.
"""
if not self.start_beat + 1e-10 < split_beat < self.end_beat - 1e-10:
# if we're asked to split at a beat that is outside the note, it has no effect
# since the expectation is a tuple as return value, return the note unaltered in a length-1 tuple
return self,
else:
second_part = self.duplicate()
second_part.start_beat = split_beat
self.length, second_part.length = PerformanceNote._split_length(self.length, split_beat - self.start_beat)
if self.pitch is not None:
if isinstance(self.pitch, Envelope):
# if the pitch is a envelope, then we split it appropriately
pitch_curve_start, pitch_curve_end = self.pitch.split_at(self.length_sum())
self.pitch = pitch_curve_start
second_part.pitch = pitch_curve_end
elif isinstance(self.pitch, tuple) and isinstance(self.pitch[0], Envelope):
# if the pitch is a tuple of envelopes (glissing chord) then same idea
first_part_chord = []
second_part_chord = []
for pitch_curve in self.pitch:
assert isinstance(pitch_curve, Envelope)
pitch_curve_start, pitch_curve_end = pitch_curve.split_at(self.length_sum())
first_part_chord.append(pitch_curve_start)
second_part_chord.append(pitch_curve_end)
def _from_dict(cls, json_dict):
return PerformanceNote(**json_dict)