Chord Families

This commit is contained in:
khodowany
2026-10-06 02:57:37 -05:00
parent df83cae38c
commit e71385dad1
16 changed files with 590 additions and 126 deletions
+5 -5
View File
@@ -52,24 +52,24 @@ class GuitarPartTests(unittest.TestCase):
generator.fretboard.validate_document(result)
sounding = [n for m in result['staves'][0]['measures'] for n in generator.score.measure_notes(m) if n['pitches']]
self.assertTrue(sounding)
self.assertTrue(all(len(n['pitches']) in (1, 3) for n in sounding))
self.assertTrue(all(len(n['pitches']) in (1, 3, 4) for n in sounding))
for n in sounding:
self.assertIn(sorted(p['tablature']['string'] for p in n['pitches']), ([2, 3, 4], [5], [6]))
self.assertIn(sorted(p['tablature']['string'] for p in n['pitches']), ([2, 3, 4], [5], [6], [2, 3, 4, 5], [2, 3, 4, 6]))
def test_explicit_bass_is_preserved_for_triads_and_extended_chords(self):
for symbol, expected in (('CM/E', 4), ('C7b9/E', 4)):
source = tests.test_musicxml.parse(tests.test_musicxml.xml_score(tests.test_musicxml.xml_note()))
chord = generator.harmony.parse_symbol(symbol)
source['staves'][0]['measures'][0]['harmonies'] = [{**chord, 'id': 'h1', 'onset': generator.model.rational(0)}]
result = tests.arrangement_fixtures.section_document(source, 'acoustic')
notes = [n for m in result['staves'][0]['measures'] for v in m['voices'] if v['id'] == 'bass' for n in v['notes']]
self.assertEqual({min(generator.model.pitch_number(p) for p in n['pitches']) % 12 for n in notes if n['pitches']}, {expected})
bass = [p for m in result['staves'][0]['measures'] for n in generator.score.measure_notes(m) for p in n['pitches'] if p['tablature']['string'] in (5, 6)]
self.assertEqual({generator.model.pitch_number(p) % 12 for p in bass}, {expected})
def test_long_melody_chords_and_short_notes(self):
content = tests.test_parts.xml_harmony() + tests.test_musicxml.xml_note('E', 2, 'half', octave=4) + tests.test_musicxml.xml_note('G', 1, 'quarter', octave=4) + tests.test_musicxml.xml_note('C', 1, 'quarter', octave=5)
notes = tests.test_musicxml.notes(self.section(content))
self.assertIn(len(notes[0]['pitches']), (3, 4))
self.assertEqual([len(n['pitches']) for n in notes[1:]], [1, 1])
self.assertEqual(generator.model.pitch_number(notes[0]['pitches'][0]), 76)
self.assertIn(sorted(p['tablature']['string'] for p in notes[0]['pitches']), ([1, 2, 3], [1, 2, 3, 4]))
self.assertIn(sorted(p['tablature']['string'] for p in notes[0]['pitches']), ([1, 2, 3], [2, 3, 4], [1, 2, 3, 4]))
def test_tied_quarters_qualify_and_keep_all_strings(self):
content = tests.test_parts.xml_harmony() + tests.test_musicxml.xml_note('E', 1, 'quarter', octave=4, extra='<tie type="start"/>') + tests.test_musicxml.xml_note('E', 1, 'quarter', octave=4, extra='<tie type="stop"/>') + '<note><rest/><duration>2</duration><type>half</type></note>'
result = self.section(content)