Span
ci / checks (push) Successful in 48m23s

This commit is contained in:
khodowany
2026-10-01 00:15:35 -05:00
parent 7b60182a3d
commit ce695a626a
10 changed files with 128 additions and 59 deletions
+19 -4
View File
@@ -29,11 +29,12 @@ class GuitarTests(unittest.TestCase):
self.assertIn(generator.fretboard.TabPosition(1, 20, 84), generator.fretboard.positions_for_pitch(fractions.Fraction(84)))
self.assertFalse(generator.fretboard.positions_for_pitch(fractions.Fraction(85)))
self.assertFalse(generator.fretboard.positions_for_pitch(fractions.Fraction(129, 2)))
self.assertTrue(generator.fretboard.within_fret_span((generator.fretboard.TabPosition(4, 11, 61), generator.fretboard.TabPosition(3, 12, 67), generator.fretboard.TabPosition(2, 14, 73))))
self.assertTrue(generator.fretboard.within_fret_span((generator.fretboard.TabPosition(4, 11, 61), generator.fretboard.TabPosition(3, 12, 67), generator.fretboard.TabPosition(2, 13, 72))))
self.assertFalse(generator.fretboard.within_fret_span((generator.fretboard.TabPosition(4, 11, 61), generator.fretboard.TabPosition(3, 12, 67), generator.fretboard.TabPosition(2, 14, 73))))
self.assertFalse(generator.fretboard.within_fret_span((generator.fretboard.TabPosition(6, 0, 40), generator.fretboard.TabPosition(1, 20, 84))))
self.assertFalse(generator.fretboard.within_fret_span((generator.fretboard.TabPosition(4, 10, 60), generator.fretboard.TabPosition(1, 20, 84))))
def test_fretted_positions_keep_span_and_proximity_scoring(self):
for frets, valid in (((1, 2, 3), True), ((1, 4), True), ((1, 5), False), ((7, 10), True), ((7, 11), False), ((12, 1, 11), False), ((3, 3), True)):
for frets, valid in (((1, 2, 3), True), ((1, 4), False), ((1, 5), False), ((7, 9), True), ((7, 10), False), ((7, 11), False), ((12, 1, 11), False), ((3, 3), True), ((18, 20), True)):
with self.subTest(frets=frets):
positions = tuple(generator.fretboard.TabPosition(6 - i, fret, 0) for i, fret in enumerate(frets))
self.assertEqual(generator.fretboard.within_fret_span(positions), valid)
@@ -42,7 +43,7 @@ class GuitarTests(unittest.TestCase):
self.assertTrue(generator.fretboard.within_fret_span(()))
def test_held_notes_obey_the_shared_three_fret_limit(self):
held = {'held': generator.fretboard.TabPosition(4, 7, 57)}
for fret, valid in ((10, True), (11, False)):
for fret, valid in ((9, True), (10, False), (11, False)):
with self.subTest(fret=fret):
pending = [('attack', (generator.fretboard.TabPosition(2, fret, 59 + fret),))]
self.assertEqual(bool(list(generator.guitar.extend_positions(held, pending))), valid)
@@ -179,13 +180,21 @@ class GuitarTests(unittest.TestCase):
self.assertTrue(all(m['transpose']['octave_change'] == -1 for m in document['staves'][0]['measures']))
def test_ties_and_overlapping_voices_keep_strings(self):
content = tests.test_musicxml.xml_note('E', 1, 'quarter', octave=4, extra='<tie type="start"/>') + tests.test_musicxml.xml_note('E', 3, 'half', octave=4, extra='<dot/><tie type="stop"/>')
content += '<backup><duration>4</duration></backup><forward><duration>1</duration></forward>' + tests.test_musicxml.xml_note('F', 3, 'half', octave=4, extra='<dot/><voice>2</voice>')
content += '<backup><duration>4</duration></backup><forward><duration>1</duration></forward>' + tests.test_musicxml.xml_note('G', 3, 'half', octave=4, extra='<dot/><voice>2</voice>')
document = tests.test_musicxml.parse(tests.test_musicxml.xml_score(content))
generator.guitar.place_guitar(document)
first, continuation, other = [p['tablature'] for m in document['staves'][0]['measures'] for v in m['voices'] for n in v['notes'] for p in n['pitches']]
self.assertEqual(first, continuation)
self.assertNotEqual(continuation['string'], other['string'])
self.assertEqual(len(generator.playback.compile_timeline(document)['events']), 2)
def test_overlapping_tones_cannot_expand_the_span_or_relocate_a_tie(self):
content = tests.test_musicxml.xml_note('E', 1, 'quarter', octave=4, extra='<tie type="start"/>') + tests.test_musicxml.xml_note('E', 3, 'half', octave=4, extra='<dot/><tie type="stop"/>')
content += '<backup><duration>4</duration></backup><forward><duration>1</duration></forward>' + tests.test_musicxml.xml_note('F', 3, 'half', octave=4, extra='<dot/><voice>2</voice>')
document = tests.test_musicxml.parse(tests.test_musicxml.xml_score(content))
before = copy.deepcopy(document)
with self.assertRaisesRegex(ValueError, '3 consecutive fret positions.*held/tied strings'):
generator.guitar.place_guitar(document)
self.assertEqual(document, before)
def test_proximity_chooses_a_path_without_relocating_tied_notes(self):
source = tests.test_musicxml.parse(tests.test_musicxml.xml_score(tests.test_musicxml.xml_note('B', 2, 'half', octave=5) + tests.test_musicxml.xml_note('C', 2, 'half', octave=6)))
generator.guitar.place_guitar(source)
@@ -263,3 +272,9 @@ class GuitarTests(unittest.TestCase):
generator.__main__.generate_assets(args)
self.assertEqual([p.name for p in output.iterdir()], ['last-good'])
self.assertEqual((output / 'last-good').read_text(), 'preserved')
harmony = '<harmony><root><root-step>C</root-step></root><kind>power</kind></harmony>'
(root / 'data/songs/0001.xml').write_text(tests.test_musicxml.xml_score(harmony + tests.test_musicxml.xml_note()))
with unittest.mock.patch('generator.rhythm.load_library', return_value=tests.rhythm_fixtures.library()), self.assertRaisesRegex(ValueError, '0001.xml, part acoustic:.*3 consecutive fret positions'):
generator.__main__.generate_assets(args)
self.assertEqual([p.name for p in output.iterdir()], ['last-good'])
self.assertEqual((output / 'last-good').read_text(), 'preserved')