Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def to_abjad(self) -> 'abjad().Component':
"""
Convert this score component to its corresponding abjad component
"""
assert abjad() is not None, "Abjad is required for this operation."
abjad_object = self._to_abjad()
lilypond_code = format(abjad_object)
if r"\glissando" in lilypond_code:
for gliss_override in ScoreComponent._gliss_overrides:
abjad().attach(abjad().LilyPondLiteral(gliss_override), abjad_object, "opening")
if r"\stemless" in lilypond_code:
abjad().attach(abjad().LilyPondLiteral(ScoreComponent._inner_stemless_def), abjad_object, "opening")
return abjad_object
# if we haven't yet encountered a measure with any pitches in it, set the clef for
# the first measure to the this clef, which is the best clef once we start getting pitches
last_clef_used = staff.measures[0].clef = this_measure_clef
elif this_measure_clef != last_clef_used:
# otherwise we simply check if this clef is new information. If it's different from the
# clef in the last measure, then we set this measure to explicitly change it
last_clef_used = measure.clef = this_measure_clef
def _to_abjad(self):
return abjad().StaffGroup([staff._to_abjad() for staff in self.staves])
def to_music_xml(self) -> pymusicxml.PartGroup:
return pymusicxml.PartGroup([staff.to_music_xml() for staff in self.staves])
class Staff(ScoreComponent, ScoreContainer):
"""
Representation of a single staff of a western-notated score
:param measures: Chronological list of Measure objects contained in this staff
:param name: Name of this staff in the score
"""
def __init__(self, measures: Sequence['Measure'], name: str = None):
ScoreContainer.__init__(self, measures, "measures", Measure)
self.name = name
@property
def measures(self) -> Sequence['Measure']:
"""Chronological list of Measure objects contained in this staff"""
return self._contents
contents_string = "\n" + textwrap.indent(",\n".join(str(x) for x in self._contents), " ") + "\n" \
if len(self._contents) > 0 else ""
return "{}({}{}=[{}])".format(
self.__class__.__name__,
extra_args_string,
self._contents_argument_name,
contents_string
)
##################################################################################################################
# User-Facing Classes
##################################################################################################################
class Score(ScoreComponent, ScoreContainer):
"""
Representation of a score in traditional western notation.
Exportable as either LilyPond or MusicXML.
:param parts: A list of parts represented by either StaffGroup or Staff objects
:param title: title to be used
:param composer: composer to be used
:param tempo_envelope: a TempoEnvelope function describing how the tempo changes over time
:ivar title: title to be used in the score
:ivar composer: composer to be written on the score
:ivar tempo_envelope: a TempoEnvelope function describing how the tempo changes over time
"""
def __init__(self, parts: Sequence[Union['Staff', 'StaffGroup']] = None, title: str = None,
composer: str = None, tempo_envelope: TempoEnvelope = None):
for same_source_group in source_id_dict.values():
_join_same_source_abjad_note_group(same_source_group)
return abjad().Tuplet(abjad().Multiplier(self.normal_divisions, self.tuplet_divisions), abjad_notes)
def to_music_xml(self, source_id_dict=None) -> pymusicxml.Tuplet:
is_top_level_call = True if source_id_dict is None else False
source_id_dict = {} if source_id_dict is None else source_id_dict
xml_note_segments = [note_segment for note_like in self.contents
for note_segment in note_like.to_music_xml(source_id_dict)]
if is_top_level_call:
for same_source_group in source_id_dict.values():
_join_same_source_xml_note_group(same_source_group)
return pymusicxml.Tuplet(xml_note_segments, (self.tuplet_divisions, self.normal_divisions))
class NoteLike(ScoreComponent):
"""
Represents a note, chord, or rest that can be notated without ties
:param pitch: float if single pitch, Envelope if a glissando, tuple if a chord, None if a rest
:param written_length: the notated length of the note, disregarding any tuplets it is part of
:param properties: a properties dictionary, same as found in a PerformanceNote
:ivar pitch: float if single pitch, Envelope if a glissando, tuple if a chord, None if a rest
:ivar written_length: the notated length of the note, disregarding any tuplets it is part of
:ivar properties: a properties dictionary, same as found in a PerformanceNote
"""
def __init__(self, pitch: Union[Envelope, float, Tuple, None], written_length: float,
properties: NotePropertiesDictionary):
self.pitch = pitch
self.written_length = Fraction(written_length).limit_denominator()
def to_music_xml(self, source_id_dict=None) -> pymusicxml.Measure:
is_top_level_call = True if source_id_dict is None else False
source_id_dict = {} if source_id_dict is None else source_id_dict
xml_voices = [voice.to_music_xml(source_id_dict) for voice in self.voices]
time_signature = (self.time_signature.numerator, self.time_signature.denominator) \
if self.show_time_signature else None
if is_top_level_call:
for same_source_group in source_id_dict.values():
_join_same_source_xml_note_group(same_source_group)
return pymusicxml.Measure(xml_voices, time_signature=time_signature, clef=self.clef)
class Voice(ScoreComponent, ScoreContainer):
"""
Representation of a single voice within a single measure of a single staff of music.
:param contents: list of Tuplet or NoteLike objects in this voice
:param time_signature: the time signature of the measure to which this voice belongs
:ivar time_signature: the time signature of the measure to which this voice belongs
"""
def __init__(self, contents: Sequence[Union['Tuplet', 'NoteLike']], time_signature: TimeSignature):
ScoreContainer.__init__(self, contents, "contents", (Tuplet, NoteLike), ("time_signature", ))
self.time_signature = time_signature
@property
def contents(self) -> Sequence[Union['Tuplet', 'NoteLike']]:
def to_abjad_lilypond_file(self) -> 'abjad().LilyPondFile':
"""
Convert and wrap as a abjad.LilyPondFile object
"""
assert abjad() is not None, "Abjad is required for this operation."
title = self.title if hasattr(self, "title") else None
composer = self.composer if hasattr(self, "composer") else None
abjad_object = self._to_abjad()
lilypond_code = format(abjad_object)
if r"\glissando" in lilypond_code:
for gliss_override in ScoreComponent._gliss_overrides:
abjad().attach(abjad().LilyPondLiteral(gliss_override), abjad_object, "opening")
abjad_lilypond_file = abjad().LilyPondFile.new(
music=abjad_object
)
# if we're actually producing the lilypond file itself, then we put the simpler
# definition of stemless outside of the main score object.
if r"\stemless" in lilypond_code:
abjad_lilypond_file.items.insert(-1, ScoreComponent._outer_stemless_def)
if title is not None:
abjad_lilypond_file.header_block.title = abjad().Markup(title)
if composer is not None:
abjad_lilypond_file.header_block.composer = abjad().Markup(composer)
composer = self.composer if hasattr(self, "composer") else None
abjad_object = self._to_abjad()
lilypond_code = format(abjad_object)
if r"\glissando" in lilypond_code:
for gliss_override in ScoreComponent._gliss_overrides:
abjad().attach(abjad().LilyPondLiteral(gliss_override), abjad_object, "opening")
abjad_lilypond_file = abjad().LilyPondFile.new(
music=abjad_object
)
# if we're actually producing the lilypond file itself, then we put the simpler
# definition of stemless outside of the main score object.
if r"\stemless" in lilypond_code:
abjad_lilypond_file.items.insert(-1, ScoreComponent._outer_stemless_def)
if title is not None:
abjad_lilypond_file.header_block.title = abjad().Markup(title)
if composer is not None:
abjad_lilypond_file.header_block.composer = abjad().Markup(composer)
return abjad_lilypond_file
parentheses="yes", font_size="5"),
guide_mark_location - measure_start)
)
this_measure_annotations.sort(key=lambda x: x[1])
xml_measure.directions_with_displacements = this_measure_annotations
measure_start += score_measure.length
return xml_score
# used in arranging voices in a part
_NumberedVoiceFragment = namedtuple("_NumberedVoiceFragment", "voice_num start_measure_num measures_with_quantizations")
_NamedVoiceFragment = namedtuple("_NamedVoiceFragment", "average_pitch start_measure_num measures_with_quantizations")
class StaffGroup(ScoreComponent, ScoreContainer):
"""
Representation of a StaffGroup (used for the multiple staves of a single instrument)
:param staves: a list of Staff objects in this group
:param name: the name of the staff group on the score
"""
def __init__(self, staves: Sequence['Staff'], name: str = None):
ScoreContainer.__init__(self, staves, "staves", Staff)
self._name = name
self._set_clefs()
@property
def name(self) -> str:
"""
_join_same_source_abjad_note_group(same_source_group)
return abjad().Staff(contents, name=self.name)
def to_music_xml(self) -> pymusicxml.Part:
source_id_dict = {}
measures = [measure.to_music_xml(source_id_dict) for measure in self.measures]
for same_source_group in source_id_dict.values():
_join_same_source_xml_note_group(same_source_group)
return pymusicxml.Part(self.name, measures)
_voice_names = [r'voiceOne', r'voiceTwo', r'voiceThree', r'voiceFour']
_voice_literals = [r'\voiceOne', r'\voiceTwo', r'\voiceThree', r'\voiceFour']
class Measure(ScoreComponent, ScoreContainer):
"""
Representation of a single measure within in a Staff
:param voices: list of voices in this measure, in numbered order
:param time_signature: the time signature for this measure
:param show_time_signature: whether or not to show the time signature. By default, when scamp is turning a
quantized Performance into a Score, this will be set to true when the time signature changes and False
otherwise.
:param clef: Which clef to use for the measure. If none, clef is left unspecified.
:ivar time_signature: the time signature for this measure
:ivar show_time_signature: Whether or not to display the time signature
:ivar clef: Which clef to use for the measure. If none, clef is left unspecified.
"""
def __init__(self, voices: Sequence['Voice'], time_signature: TimeSignature, show_time_signature: bool = True,
clef: Optional[str] = None):
beat_group = []
out.append(this_item.to_music_xml(source_id_dict))
t += this_item.length()
if len(beat_group) > 0:
out.append(pymusicxml.BeamedGroup(beat_group))
assert len(contents) == 0 # we should have gone through everything at this point
if is_top_level_call:
for same_source_group in source_id_dict.values():
_join_same_source_xml_note_group(same_source_group)
return out
class Tuplet(ScoreComponent, ScoreContainer):
"""
Representation of a Tuplet object within a single voice of music.
Reads as: tuplet_divisions in the space of normal_divisions of division_length
e.g. 7, 4, and 0.25 would mean '7 in the space of 4 sixteenth notes'
:param tuplet_divisions: The new number that the tuplet is divided into
:param normal_divisions: the normal number of divisions of division_length that would fill the time
:param division_length: length in quarter notes of the tuplet note type
:param contents: List of NoteLike objects (notes and rests) contained in this tuplet
:ivar tuplet_divisions: The new number that the tuplet is divided into
:ivar normal_divisions: the normal number of divisions of division_length that would fill the time
:ivar division_length: length in quarter notes of the tuplet note type
"""
def __init__(self, tuplet_divisions: int, normal_divisions: int, division_length: float,
contents: Sequence['NoteLike'] = None):