Generation
This commit is contained in:
+24
-17
@@ -161,7 +161,7 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
item = generator.accompaniment.context(measure, None)
|
||||
bar = quarter_bar(4, {0, 1})
|
||||
self.assertEqual(generator.accompaniment.sounding_spans(bar, item), ())
|
||||
self.assertEqual(generator.accompaniment.rank(bar, [(item, ())], False)[0], 1)
|
||||
self.assertEqual(generator.accompaniment.rank(bar, [(item, ())], 'upper')[0], 1)
|
||||
def test_melody_context_uses_audible_hidden_notes_but_not_cues(self):
|
||||
measure = melody_measures(1)[0]
|
||||
notes = measure['voices'][0]['notes']
|
||||
@@ -177,7 +177,7 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
content = tests.test_parts.xml_harmony() + tests.test_musicxml.xml_note()
|
||||
measures = tests.test_musicxml.parse(xml_bars([content] * 4))['staves'][0]['measures']
|
||||
plan = generator.accompaniment.plan_section(measures, library)
|
||||
self.assertEqual(plan.acoustic, (sounding,) * 4)
|
||||
self.assertEqual(plan.acoustic_upper, (sounding,) * 4)
|
||||
self.assertEqual(plan.electric, (silent,) * 4)
|
||||
def test_section_repeats_four_bar_motif_with_at_most_one_beat_variation(self):
|
||||
for beats in (2, 3, 4, 5):
|
||||
@@ -185,7 +185,7 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
before = copy.deepcopy(measures)
|
||||
library = tests.rhythm_fixtures.library()
|
||||
plan = generator.accompaniment.plan_section(measures, library)
|
||||
for part in (plan.acoustic, plan.electric):
|
||||
for part in (plan.acoustic_bass, plan.acoustic_upper, plan.electric):
|
||||
with self.subTest(beats=beats, part=part):
|
||||
self.assertEqual(len(part), 12)
|
||||
self.assertEqual(part[:4], part[4:8])
|
||||
@@ -201,7 +201,7 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
measures = tests.test_musicxml.parse(xml_bars([content] * 4))['staves'][0]['measures']
|
||||
plan = generator.accompaniment.plan_section(measures, tests.rhythm_fixtures.library())
|
||||
for index in range(3):
|
||||
acoustic, electric = set(plan.acoustic[index].attacks()), set(plan.electric[index].attacks())
|
||||
acoustic, electric = set(plan.acoustic_upper[index].attacks()), set(plan.electric[index].attacks())
|
||||
self.assertTrue(acoustic)
|
||||
self.assertTrue(electric)
|
||||
self.assertFalse(acoustic & electric)
|
||||
@@ -212,11 +212,13 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
plan = generator.accompaniment.plan_section(measures, tests.rhythm_fixtures.library())
|
||||
for index, measure in enumerate(measures):
|
||||
melody = {generator.model.fraction(n['onset']) for n in measure['voices'][0]['notes']}
|
||||
for bars in (plan.acoustic, plan.electric):
|
||||
for bars in (plan.acoustic_bass, plan.acoustic_upper, plan.electric):
|
||||
events = generator.accompaniment.realize(measure, bars[index], None)
|
||||
attacks = {generator.model.fraction(n['onset']) for n in events if n['kind'] == 'note'}
|
||||
self.assertTrue(attacks, (index, bars))
|
||||
self.assertTrue(attacks & melody)
|
||||
if bars is not plan.electric:
|
||||
self.assertTrue(attacks, (index, bars))
|
||||
self.assertTrue(attacks <= melody)
|
||||
self.assertTrue(any(bar.attacks() for bar in plan.electric))
|
||||
def test_section_and_local_meter_changes_restart_the_motif(self):
|
||||
library = generator.rhythm.Library(tuple(generator.rhythm.Snippet(f'{beats}-4/pair', f'{beats}/4', (quarter_bar(beats, {0}), quarter_bar(beats, {1}))) for beats in (3, 4)))
|
||||
segments = [melody_measures(3), melody_measures(2, beats=3), melody_measures(3), melody_measures(4)]
|
||||
@@ -226,9 +228,10 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
start = 0
|
||||
for segment in segments:
|
||||
expected = generator.accompaniment.plan_section(segment, library)
|
||||
self.assertEqual(plan.acoustic[start:start + len(segment)], expected.acoustic)
|
||||
self.assertEqual(plan.acoustic_upper[start:start + len(segment)], expected.acoustic_upper)
|
||||
self.assertEqual(plan.acoustic_bass[start:start + len(segment)], expected.acoustic_bass)
|
||||
self.assertEqual(plan.electric[start:start + len(segment)], expected.electric)
|
||||
self.assertEqual(plan.acoustic[start].attacks(), (0,))
|
||||
self.assertEqual(plan.acoustic_upper[start].attacks(), (0,))
|
||||
start += len(segment)
|
||||
def test_mid_measure_meter_changes_and_unsupported_meters_fail(self):
|
||||
content = tests.test_parts.xml_harmony() + tests.test_musicxml.xml_note(duration=1, kind='quarter') + '<attributes><time><beats>3</beats><beat-type>4</beat-type></time></attributes>' + tests.test_musicxml.xml_note(duration=3, kind='half', extra='<dot/>')
|
||||
@@ -248,8 +251,8 @@ class AccompanimentPlanningTests(unittest.TestCase):
|
||||
contexts = [generator.accompaniment.context(m, chord) for m, chord in zip(measures, previous)]
|
||||
self.assertEqual([item.intervals for item in contexts], [((0, 4),), ((0, 2),), ()])
|
||||
plan = generator.accompaniment.plan_section(measures, tests.rhythm_fixtures.library(), initial=initial)
|
||||
self.assertTrue(generator.accompaniment.sounding_attacks(plan.acoustic[0], contexts[0]))
|
||||
self.assertEqual(generator.accompaniment.sounding_attacks(plan.acoustic[2], contexts[2]), ())
|
||||
self.assertTrue(generator.accompaniment.sounding_attacks(plan.acoustic_upper[0], contexts[0]))
|
||||
self.assertEqual(generator.accompaniment.sounding_attacks(plan.acoustic_upper[2], contexts[2]), ())
|
||||
|
||||
class AccompanimentRealizationTests(unittest.TestCase):
|
||||
def test_harmonic_gating_removes_dangling_beams(self):
|
||||
@@ -294,7 +297,8 @@ class AccompanimentRealizationTests(unittest.TestCase):
|
||||
self.assertEqual(events[1]['written'], {'type': 'quarter', 'dots': 0})
|
||||
library = generator.rhythm.Library((generator.rhythm.Snippet('pickup', '4/4', (bar,)),))
|
||||
plan = generator.accompaniment.plan_section([measure], library)
|
||||
self.assertEqual(plan.acoustic, (bar,))
|
||||
self.assertEqual(plan.acoustic_upper, (bar,))
|
||||
self.assertEqual(plan.acoustic_bass, (bar,))
|
||||
self.assertEqual(plan.electric, (bar,))
|
||||
|
||||
class TiedAccompanimentTests(unittest.TestCase):
|
||||
@@ -326,7 +330,8 @@ class TiedAccompanimentTests(unittest.TestCase):
|
||||
bars = library.for_meter('4/4')[0].bars
|
||||
self.assertEqual(bars[1].attacks(), ())
|
||||
plan = generator.accompaniment.plan_section(source['staves'][0]['measures'], library)
|
||||
self.assertEqual(plan.acoustic, bars)
|
||||
self.assertEqual(plan.acoustic_upper, bars)
|
||||
self.assertEqual(plan.acoustic_bass, bars)
|
||||
self.assertEqual(plan.electric, bars)
|
||||
result = generator.practice.generate.practice_document(source, 'acoustic', rhythms=library)
|
||||
first, second = tests.test_musicxml.notes(result), tests.test_musicxml.notes(result, 1)
|
||||
@@ -337,11 +342,13 @@ class TiedAccompanimentTests(unittest.TestCase):
|
||||
self.assertEqual(second[1]['pitches'], [])
|
||||
self.assertEqual(timing(second), expected)
|
||||
self.assert_tied_chord(first[0], second[0])
|
||||
self.assertEqual({generator.model.pitch_number(p) % 12 for p in first[0]['pitches']}, {0, 4, 7})
|
||||
first_tones = [p for v in result['staves'][0]['measures'][0]['voices'] for n in v['notes'] for p in n['pitches']]
|
||||
self.assertEqual({generator.model.pitch_number(p) % 12 for p in first_tones}, {0, 4, 7})
|
||||
self.assert_tied_chord(result['staves'][0]['measures'][0]['voices'][1]['notes'][0], result['staves'][0]['measures'][1]['voices'][1]['notes'][0])
|
||||
generator.model.validate_document(result)
|
||||
timeline = generator.playback.compile_timeline(result)
|
||||
self.assertEqual(generator.model.fraction(timeline['duration']), 8)
|
||||
self.assertEqual(len(timeline['events']), len(first[0]['pitches']))
|
||||
self.assertEqual(len(timeline['events']), len(first_tones))
|
||||
self.assertTrue(all(generator.model.fraction(e['onset']) == 0 and generator.model.fraction(e['duration']) == 4 + continuation_duration for e in timeline['events']))
|
||||
self.assertEqual(source, before)
|
||||
self.assertEqual(library.for_meter('4/4')[0].bars, bars)
|
||||
@@ -354,7 +361,7 @@ class TiedAccompanimentTests(unittest.TestCase):
|
||||
first, second = tests.test_musicxml.notes(result), tests.test_musicxml.notes(result, 1)
|
||||
self.assertEqual(timing(first), [(0, 4, 'note')])
|
||||
self.assertEqual(timing(second), [(0, 2, 'rest'), (2, 2, 'rest')])
|
||||
self.assertEqual({generator.model.pitch_number(p) % 12 for p in first[0]['pitches']}, {0, 4, 7})
|
||||
self.assertEqual({generator.model.pitch_number(p) % 12 for v in result['staves'][0]['measures'][0]['voices'] for n in v['notes'] for p in n['pitches']}, {0, 4, 7})
|
||||
self.assertEqual(second[0]['pitches'], [])
|
||||
for note in first + second:
|
||||
for pitch in note['pitches']:
|
||||
@@ -374,5 +381,5 @@ class TiedAccompanimentTests(unittest.TestCase):
|
||||
self.assert_tied_chord(first[0], second[0])
|
||||
generator.model.validate_document(result)
|
||||
events = generator.playback.compile_timeline(result)['events']
|
||||
self.assertEqual(len(events), len(first[0]['pitches']))
|
||||
self.assertEqual(len(events), sum(len(n['pitches']) for v in result['staves'][0]['measures'][0]['voices'] for n in v['notes']))
|
||||
self.assertTrue(all(generator.model.fraction(e['onset']) == 0 and generator.model.fraction(e['duration']) == 5 for e in events))
|
||||
|
||||
Reference in New Issue
Block a user