Пример #1
0
 def test_middle_c_at_with_explicit_clefs(self):
     staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable)
     Clef(staff, Mm(0), "treble")
     Clef(staff, Mm(10), "bass")
     # Test between two clefs should be in treble mode
     assert staff.middle_c_at(Mm(1)) == staff.unit(5)
     # Test after bass clef goes into effect
     assert staff.middle_c_at(Mm(11)) == staff.unit(-1)
Пример #2
0
 def test_position_on_ledger_with_odd_line_count(self):
     staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=5)
     assert staff.y_on_ledger(staff.unit(-1)) is True
     assert staff.y_on_ledger(staff.unit(-0.5)) is False
     assert staff.y_on_ledger(staff.unit(0)) is False
     assert staff.y_on_ledger(staff.unit(4)) is False
     assert staff.y_on_ledger(staff.unit(4.5)) is False
     assert staff.y_on_ledger(staff.unit(5)) is True
Пример #3
0
class TestFlag(unittest.TestCase):
    def setUp(self):
        neoscore.setup()
        self.staff = Staff((Mm(0), Mm(0)), Mm(100), flowable=None)

    def test_glyphnames(self):
        # All flags with durations in the following denominations should
        # be init-able without error.
        for i in [1024, 512, 256, 128, 64, 32, 16, 8]:
            Flag(Beat(1, i), 1, self.staff)
            Flag(Beat(1, i), -1, self.staff)

    def test_invalid_direction_raises_value_error(self):
        with pytest.raises(ValueError):
            Flag(Beat(1, 8), 0, self.staff)
        with pytest.raises(ValueError):
            Flag(Beat(1, 8), 2, self.staff)
        with pytest.raises(ValueError):
            Flag(Beat(1, 8), -2, self.staff)

    def test_needs_flag(self):
        assert Flag.needs_flag(Beat(1, 4)) is False
        assert Flag.needs_flag(Beat(1, 2)) is False
        assert Flag.needs_flag(Beat(1, 8)) is True
        assert Flag.needs_flag(Beat(1, 16)) is True

    def test_vertical_offset_needed(self):
        self.assertEqual(
            Flag.vertical_offset_needed(Beat(1, 4), self.staff.unit),
            self.staff.unit(0))

        self.assertEqual(
            Flag.vertical_offset_needed(Beat(1, 8), self.staff.unit),
            self.staff.unit(1))

        self.assertEqual(
            Flag.vertical_offset_needed(Beat(1, 16), self.staff.unit),
            self.staff.unit(1),
        )

    def test_raises_no_flag_needed_error(self):
        # Test valid durations
        Flag(Beat(1, 16), 1, self.staff)
        Flag(Beat(1, 8), 1, self.staff)

        # Test invalid durations
        with pytest.raises(NoFlagNeededError):
            Flag(Beat(1, 4), 1, self.staff)
        with pytest.raises(NoFlagNeededError):
            Flag(Beat(1, 2), 1, self.staff)
        with pytest.raises(NoFlagNeededError):
            Flag(Beat(1, 1), 1, self.staff)
Пример #4
0
 def test_middle_c_at_with_active_octave_line(self):
     staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable)
     Clef(staff, Mm(0), "treble")
     octave_line = OctaveLine((Mm(20), Mm(0)),
                              staff,
                              Mm(80),
                              indication="8va")
     # Before octave_line goes into effect
     assert staff.middle_c_at(Mm(0)) == staff.unit(5)
     # While octave_line is in effect
     assert staff.middle_c_at(Mm(20)) == staff.unit(8.5)
     assert staff.middle_c_at(Mm(100)) == staff.unit(8.5)
     # After octave_line ends
     assert staff.middle_c_at(Mm(101)) == staff.unit(5)
Пример #5
0
class TestMultiStaffObject(unittest.TestCase):
    def setUp(self):
        neoscore.setup()
        self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5))
        self.staff_1 = Staff((Mm(0), Mm(0)), Mm(100), self.flowable)
        self.staff_2 = Staff((Mm(0), Mm(30)), Mm(100), self.flowable)
        self.staff_3 = Staff((Mm(0), Mm(50)), Mm(100), self.flowable)

    def test_visually_sorted_staves(self):
        multi_object = MultiStaffObject(
            {self.staff_1, self.staff_2, self.staff_3})
        assert multi_object.visually_sorted_staves == [
            self.staff_1,
            self.staff_2,
            self.staff_3,
        ]

    def test_highest_staff(self):
        multi_object = MultiStaffObject(
            {self.staff_1, self.staff_2, self.staff_3})
        assert multi_object.highest_staff == self.staff_1

    def test_lowest_staff(self):
        multi_object = MultiStaffObject(
            {self.staff_1, self.staff_2, self.staff_3})
        assert multi_object.lowest_staff == self.staff_3

    def test_vertical_span(self):
        multi_object = MultiStaffObject(
            {self.staff_1, self.staff_2, self.staff_3})
        assert_almost_equal(multi_object.vertical_span,
                            self.staff_3.unit(4) + Mm(50))
Пример #6
0
 def __init__(
     self,
     pos_x: Unit,
     staff: Staff,
     pitches: Optional[list[PitchDef]],
     duration: BeatDef,
     stem_direction: Optional[int] = None,
 ):
     """
     Args:
         pos_x: The horizontal position
         staff: The staff the object is attached to
         pitches: A list of pitch strings representing noteheads.
             An empty list or `None` indicates a rest.
         duration: The duration of the Chordrest
         stem_direction: An optional stem direction override
             where `1` points down and `-1` points up. If omitted, the
             direction is automatically calculated to point away from
             the furthest-out notehead.
     """
     StaffObject.__init__(self, staff)
     ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff, None)
     self.duration = duration
     self._noteheads = set()
     self._accidentals = set()
     self._ledgers = set()
     self._dots = set()
     self._noteheads = set()
     self._stem_direction_override = stem_direction
     if pitches:
         for pitch in pitches:
             self._noteheads.add(Notehead(staff.unit(0), pitch, self.duration, self))
         self.rest = None
     else:
         # TODO LOW support explicit rest Y positioning
         self.rest = Rest(Point(staff.unit(0), staff.unit(2)), self, duration)
     self._stem = None
     self._flag = None
Пример #7
0
 def __init__(
     self,
     pos_x: Unit,
     staff: Staff,
     key_signature_type: Union[KeySignatureType, str],
 ):
     """
     Args:
         pos_x (Unit): The x position relative to the parent staff.
         staff (Staff): The parent staff
         key_signature_type (KeySignatureType or str): A description of the
             key signature. Any KeySignatureType may be used, or a str
             of one's name.
     """
     ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff)
     StaffObject.__init__(self, staff)
     self._key_signature_type = (
         key_signature_type
         if isinstance(key_signature_type, KeySignatureType) else
         KeySignatureType[key_signature_type.upper()])
     self._create_pseudo_accidentals()
Пример #8
0
    def __init__(self, staff: Staff, pos_x: Unit, clef_type: Union[ClefType,
                                                                   str]):
        """
        Args:
            staff (Staff):
            pos_x (Unit):
            clef_type (ClefType or str): The type of clef.
                For convenience, any `str` of a `ClefType`
                enum name may be passed.

        Raises:
            KeyError: If the given `clef_type` is not a valid
                `ClefType` or `ClefType` enum name.
        """
        if isinstance(clef_type, ClefType):
            self._clef_type = clef_type
        else:
            self._clef_type = ClefType[clef_type.upper()]
        MusicText.__init__(self, (pos_x, staff.unit(0)),
                           self._canonical_names[self._clef_type], staff)
        StaffObject.__init__(self, staff)
        self.y = self.staff_position
Пример #9
0
class TestNotehead(unittest.TestCase):
    def setUp(self):
        neoscore.setup()
        self.flowable = Flowable((Mm(0), Mm(0)), Mm(10000), Mm(30), Mm(5))
        self.staff = Staff((Mm(0), Mm(0)), Mm(10000), flowable=self.flowable)
        Clef(self.staff, Mm(0), "treble")

    def test_staff_position_middle_c_treble(self):
        self.assertEqual(
            Notehead(Mm(10), "c'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(5)
        )

    def test_staff_position_low_octaves(self):
        self.assertEqual(
            Notehead(Mm(10), "c", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(8.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "c,", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(12),
        )
        self.assertEqual(
            Notehead(Mm(10), "c,,", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(15.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "c,,,", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(19),
        )

    def test_staff_position_high_octaves(self):
        self.assertEqual(
            Notehead(Mm(10), "c''", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(1.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "c'''", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(-2),
        )
        self.assertEqual(
            Notehead(Mm(10), "c''''", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(-5.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "c'''''", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(-9),
        )

    def test_staff_position_with_accidentals(self):
        self.assertEqual(
            Notehead(Mm(10), "cf'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(5),
        )
        self.assertEqual(
            Notehead(Mm(10), "cn'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(5),
        )
        self.assertEqual(
            Notehead(Mm(10), "cs'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(5),
        )

    def test_staff_position_with_all_letter_names(self):
        self.assertEqual(
            Notehead(Mm(10), "d'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(4.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "e'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(4)
        )
        self.assertEqual(
            Notehead(Mm(10), "f'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(3.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "g'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(3)
        )
        self.assertEqual(
            Notehead(Mm(10), "a'", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(2.5),
        )
        self.assertEqual(
            Notehead(Mm(10), "b'", Beat(1, 4), self.staff).staff_pos, self.staff.unit(2)
        )

    def test_staff_position_on_later_flowable_line(self):
        self.assertEqual(
            Notehead(Mm(1000), "c", Beat(1, 4), self.staff).staff_pos,
            self.staff.unit(8.5),
        )
Пример #10
0
 def test_ledgers_needed_from_position_with_odd_line_count(self):
     staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=5)
     # Inside the staff, no ledgers
     assert staff.ledgers_needed_for_y(staff.unit(0)) == []
     assert staff.ledgers_needed_for_y(staff.unit(4)) == []
     # Just outside the staff, no ledgers
     assert staff.ledgers_needed_for_y(staff.unit(-0.5)) == []
     assert staff.ledgers_needed_for_y(staff.unit(4.5)) == []
     # Right on the first ledger
     assert staff.ledgers_needed_for_y(staff.unit(-1)) == [staff.unit(-1)]
     assert staff.ledgers_needed_for_y(staff.unit(5)) == [staff.unit(5)]
     # Further outside with multiple ledgers, directly on lines
     assert staff.ledgers_needed_for_y(staff.unit(6)) == [
         staff.unit(6),
         staff.unit(5),
     ]
     assert staff.ledgers_needed_for_y(staff.unit(-2)) == [
         staff.unit(-2),
         staff.unit(-1),
     ]
     # Further outside with multiple ledgers, between lines
     assert staff.ledgers_needed_for_y(staff.unit(6.5)) == [
         staff.unit(6),
         staff.unit(5),
     ]
     assert staff.ledgers_needed_for_y(staff.unit(-2.5)) == [
         staff.unit(-2),
         staff.unit(-1),
     ]
Пример #11
0
 def test_position_inside_staff_with_even_line_count(self):
     staff = Staff((Mm(0), Mm(0)), Mm(100), self.flowable, line_count=4)
     assert staff.y_inside_staff(staff.unit(0)) is True
     assert staff.y_inside_staff(staff.unit(3)) is True
     assert staff.y_inside_staff(staff.unit(4)) is False
     assert staff.y_inside_staff(staff.unit(-4)) is False
Пример #12
0
class TestChordrest(unittest.TestCase):
    def setUp(self):
        neoscore.setup()
        self.flowable = Flowable(Point(Mm(0), Mm(0)), Mm(10000), Mm(100))
        self.staff = Staff(Point(Mm(0), Mm(0)), Mm(100), self.flowable)
        Clef(self.staff, Mm(0), "treble")

    def test_ledger_line_positions(self):
        pitches = ["c'", "b'", "f'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.ledger_line_positions == [
            self.staff.unit(5),
            self.staff.unit(-3),
            self.staff.unit(-2),
            self.staff.unit(-1),
        ]

    def test_ledger_line_positions_with_different_clef(self):
        Clef(self.staff, Mm(10), "bass")
        pitches = ["e,", "d", "e'"]
        chord = Chordrest(Mm(15), self.staff, pitches, Beat(1, 4))
        assert chord.ledger_line_positions == [
            self.staff.unit(5),
            self.staff.unit(-2),
            self.staff.unit(-1),
        ]

    def test_rhythm_dot_positions_with_rest(self):
        chord = Chordrest(Mm(1), self.staff, None, Beat(7, 16))
        dots = list(chord.rhythm_dot_positions)
        dots.sort(key=lambda d: d.x)
        assert_almost_equal(
            dots[0], Point(self.staff.unit(1.326), self.staff.unit(1.5))
        )
        assert_almost_equal(
            dots[1], Point(self.staff.unit(1.826), self.staff.unit(1.5))
        )

    def test_rhythm_dot_positions_with_noteheads(self):
        pitches = ["e,", "d", "e'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(7, 16))
        dots = list(chord.rhythm_dot_positions)
        dots.sort(key=lambda d: d.x)
        dots.sort(key=lambda d: d.y)
        assert_almost_equal(
            dots[0], Point(self.staff.unit(1.43), self.staff.unit(-3.5))
        )
        assert_almost_equal(
            dots[1], Point(self.staff.unit(1.93), self.staff.unit(-3.5))
        )
        assert_almost_equal(dots[2], Point(self.staff.unit(1.43), self.staff.unit(7.5)))
        assert_almost_equal(dots[3], Point(self.staff.unit(1.93), self.staff.unit(7.5)))
        assert_almost_equal(
            dots[4], Point(self.staff.unit(1.43), self.staff.unit(10.5))
        )
        assert_almost_equal(
            dots[5], Point(self.staff.unit(1.93), self.staff.unit(10.5))
        )

    def test_furthest_notehead_with_one_note(self):
        pitches = ["b'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("b'")
        pitches = ["f'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("f'''")
        pitches = ["c,,,,"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("c,,,,")

    def test_furthest_notehead_with_many_notes(self):
        pitches = ["b''", "bs'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("b''")
        pitches = ["b'", "b,,,"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("b,,,")
        pitches = ["f''''", "b"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("f''''")
        pitches = ["c'", "c,,,,", "b'", "c'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.furthest_notehead.pitch == Pitch("c,,,,")

    def test_highest_notehead(self):
        pitches = ["c'", "b'", "c'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.highest_notehead.pitch == Pitch("c'''")

    def test_lowest_notehead(self):
        pitches = ["c'", "b'", "c'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.lowest_notehead.pitch == Pitch("c'")

    def test_highest_and_lowest_notehead_same_with_one_note(self):
        pitches = ["c'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.highest_notehead == chord.lowest_notehead

    def test_stem_direction_down(self):
        pitches = ["c'", "b'", "c''''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.stem_direction == 1

    def test_stem_direction_up(self):
        pitches = ["c,,,,,", "b'", "c'''"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.stem_direction == -1

    def test_stem_direction_down_with_one_note_at_staff_center(self):
        pitches = ["b'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert chord.stem_direction == 1

    def test_stem_direction_override(self):
        pitches = ["b'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4), -1)
        assert chord.stem_direction == -1
        # Setting stem_direction = None should revert to default 1
        chord.stem_direction = None
        assert chord.stem_direction == 1

    def test_stem_height_min(self):
        pitches = ["b'"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert_almost_equal(chord.stem_height, self.staff.unit(3))

    def test_stem_height_fitted(self):
        pitches = ["c'''", "g"]
        chord = Chordrest(Mm(1), self.staff, pitches, Beat(1, 4))
        assert_almost_equal(chord.stem_height, self.staff.unit(-10.5))