+16
-14
@@ -3,7 +3,9 @@ import fractions
|
||||
import unittest
|
||||
|
||||
import generator.accompaniment
|
||||
import generator.acoustic_voicing
|
||||
import generator.arrange.generate
|
||||
import generator.fretboard
|
||||
import generator.guitar
|
||||
import generator.harmony
|
||||
import generator.model
|
||||
@@ -27,19 +29,19 @@ class GuitarPartTests(unittest.TestCase):
|
||||
for profile in ('acoustic', 'electric'):
|
||||
with self.subTest(symbol=symbol, profile=profile):
|
||||
definition = generator.harmony.parse_symbol(symbol)
|
||||
requirements = generator.guitar.chord_requirements(definition, profile)
|
||||
candidates = generator.guitar.chord_positions(requirements, profile=profile)
|
||||
requirements = generator.fretboard.chord_requirements(definition, respect_bass=profile != 'electric')
|
||||
candidates = generator.acoustic_voicing.candidates(requirements) if profile == 'acoustic' else generator.guitar.chord_positions(requirements, profile=profile)
|
||||
self.assertTrue(candidates)
|
||||
for candidate in candidates:
|
||||
strings = tuple(p.string_number for p in candidate)
|
||||
self.assertIn(strings, generator.guitar.ACOUSTIC_STRINGS if profile == 'acoustic' else generator.guitar.ELECTRIC_STRINGS)
|
||||
self.assertIn(strings, ((5, 4, 3, 2), (6, 4, 3, 2)) if profile == 'acoustic' else generator.guitar.ELECTRIC_STRINGS)
|
||||
self.assertTrue(requirements.covers({p.midi % 12 for p in candidate}))
|
||||
self.assertTrue({p.midi % 12 for p in candidate} <= set(requirements.allowed))
|
||||
self.assertTrue(generator.guitar.within_fret_span(candidate))
|
||||
self.assertTrue(generator.fretboard.within_fret_span(candidate))
|
||||
self.assertTrue(all(1 <= p.fret <= 20 for p in candidate))
|
||||
chord = generator.harmony.parse_symbol('C7')
|
||||
self.assertNotIn(0, generator.guitar.chord_requirements(chord, 'electric').required)
|
||||
candidates = generator.guitar.chord_positions(generator.guitar.chord_requirements(chord, 'electric'), profile='electric')
|
||||
self.assertNotIn(0, generator.fretboard.chord_requirements(chord, respect_bass=False).required)
|
||||
candidates = generator.guitar.chord_positions(generator.fretboard.chord_requirements(chord, respect_bass=False), profile='electric')
|
||||
self.assertTrue(any(all(p.midi % 12 != 0 for p in c) for c in candidates))
|
||||
def test_acoustic_combines_independent_rhythms_with_a_fixed_grip(self):
|
||||
result = self.section(tests.test_parts.xml_harmony() + tests.test_musicxml.xml_note(), 'acoustic')
|
||||
@@ -59,17 +61,17 @@ class GuitarPartTests(unittest.TestCase):
|
||||
self.assertNotIn('stem', note)
|
||||
strings = sorted(p['tablature']['string'] for p in note['pitches'] if p['tablature']['string'] <= 4)
|
||||
if strings:
|
||||
self.assertIn(strings, ([2, 3], [3, 4], [2, 3, 4]))
|
||||
self.assertEqual(strings, [2, 3, 4])
|
||||
timeline = generator.playback.compile_timeline(result)['events']
|
||||
by_id = {p['id']: p for v in measure['voices'] for n in v['notes'] for p in n['pitches']}
|
||||
for event in timeline:
|
||||
start = generator.model.fraction(event['onset'])
|
||||
simultaneous = [e for e in timeline if generator.model.fraction(e['onset']) <= start < generator.model.fraction(e['onset']) + generator.model.fraction(e['duration'])]
|
||||
positions = [generator.guitar.TabPosition(by_id[e['id']]['tablature']['string'], by_id[e['id']]['tablature']['fret'], int(generator.model.fraction(e['pitch']))) for e in simultaneous]
|
||||
positions = [generator.fretboard.TabPosition(by_id[e['id']]['tablature']['string'], by_id[e['id']]['tablature']['fret'], int(generator.model.fraction(e['pitch']))) for e in simultaneous]
|
||||
self.assertEqual(len(positions), len({p.string_number for p in positions}))
|
||||
self.assertTrue(generator.guitar.within_fret_span(positions))
|
||||
def test_explicit_bass_and_default_root(self):
|
||||
for symbol, expected in (('CM/E', 4), ('C7b9', 0)):
|
||||
self.assertTrue(generator.fretboard.within_fret_span(positions))
|
||||
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)}]
|
||||
@@ -88,9 +90,9 @@ class GuitarPartTests(unittest.TestCase):
|
||||
self.assertEqual([generator.model.fraction(n['onset']) for n in notes if n['pitches']], [0, 2])
|
||||
for onset in (0, 2):
|
||||
pitches = [p for n in notes if generator.model.fraction(n['onset']) == onset for p in n['pitches']]
|
||||
positions = [generator.guitar.TabPosition(p['tablature']['string'], p['tablature']['fret'], int(generator.model.pitch_number(p) - 12)) for p in pitches]
|
||||
self.assertIn(tuple(sorted((p.string_number for p in positions), reverse=True)), generator.guitar.ACOUSTIC_STRINGS)
|
||||
self.assertTrue(generator.guitar.within_fret_span(positions))
|
||||
positions = [generator.fretboard.TabPosition(p['tablature']['string'], p['tablature']['fret'], int(generator.model.pitch_number(p) - 12)) for p in pitches]
|
||||
self.assertIn(tuple(sorted((p.string_number for p in positions), reverse=True)), ((5, 4, 3, 2), (6, 4, 3, 2)))
|
||||
self.assertTrue(generator.fretboard.within_fret_span(positions))
|
||||
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))
|
||||
|
||||
Reference in New Issue
Block a user