This commit is contained in:
khodowany
2026-10-04 18:48:02 -05:00
parent 68df7292ee
commit 0e68f5364b
58 changed files with 1416 additions and 7567 deletions
+4 -68
View File
@@ -10,10 +10,10 @@ import unittest
from audition import reference_review, solo_compare
from generator import vocabulary, production
from generator.solo import export, gesture_rhythm, harmonic, notation, placement, routes, themes, types
from tests.test_solo import song
from tests.test_solo_development import note
from tests.test_solo_passages import choices
from generator.solo import export, harmonic, notation, placement, routes, types
from tests.solo_fixtures import song
from tests.solo_fixtures import note
from tests.solo_fixtures import choices
from tests import solo_fixtures
@@ -116,70 +116,6 @@ class ComparisonTests(unittest.TestCase):
self.assertTrue((root/'solo_xml'/'fixture-solo2.xml').is_file())
class MusicalSelectionTests(unittest.TestCase):
def test_cell_purpose_survives_loading_and_filters_eligibility(self):
cells=tuple(vocabulary.rhythm_cells(120,'arrival'))
self.assertTrue(cells)
self.assertTrue(all(c.purpose=='arrival' for c in cells))
self.assertFalse(any(c.id=='short_answer' for c in cells))
def test_connecting_rhythm_prefers_groups_to_isolated_notes(self):
joined=((F(),F(1,2)),(F(1,2),F(3,2)),(F(3,2),F(2)))
fragmented=((F(),F(1,2)),(F(1),F(3,2)),(F(2),F(5,2)))
self.assertLess(themes.rhythm_cost(joined,F(4),'connect'),themes.rhythm_cost(fragmented,F(4),'connect'))
def test_complete_signature_boundary_can_cross_barline(self):
home=SimpleNamespace(signature=(note(0,2),note(2,5)))
source=SimpleNamespace(end=F(24));ending=SimpleNamespace(earliest=F(21))
self.assertEqual(themes.unit_end(source,F(8),home,ending,F(4)),13)
def test_arpeggio_is_not_charged_for_each_nonstep_interval(self):
chord=(note(0,F(1,2),'c'),note(F(1,2),1,'e'),note(1,F(3,2),'g'))
steps=(note(0,F(1,2),'c'),note(F(1,2),1,'d'),note(1,F(3,2),'e'))
self.assertEqual(routes.path_cost(chord),routes.path_cost(steps))
h=harmonic.Harmony(choices(('CM7',)))
self.assertEqual(routes.path_family(chord,h)[0],'arpeggio')
self.assertEqual(routes.path_family(steps,h)[0],'mapped')
run=tuple(note(i,F(i+1),p) for i,p in enumerate(('c','d','e','f','g','a')))
self.assertEqual(routes.path_cost(run),0)
oscillation=tuple(note(i,F(i+1),p) for i,p in enumerate(('c','d','c','d','c')))
self.assertGreater(routes.path_cost(oscillation),0)
def test_data_driven_arpeggio_reaches_exact_destination_as_one_route(self):
h=harmonic.Harmony(choices(('CM7',)))
notes=(note(0,F(1,2),'c',event_id='first'),note(F(1,2),1,'c',event_id='middle'),note(1,F(3,2),'g',event_id='target'))
paths=routes.candidates(notes,{'target'},h,solo_fixtures.library(),(41,76))
authored=[r for r in paths if any(s.startswith('chord-path:') for s in r.sources)]
self.assertTrue(authored)
self.assertTrue(any([n.pitch.number() for n in r.notes]==[60,64,67] for r in authored))
self.assertTrue(all(r.notes[-1].pitch==notes[-1].pitch for r in paths))
self.assertTrue(all(h.evaluate(r.notes).valid for r in paths))
def test_solo_vocabulary_changes_do_not_change_accompaniment_inputs(self):
resources=vocabulary.load()
changed=copy.deepcopy(resources)
changed['melodic_vocabulary']['cells'].append({'id':'independent-test'})
for role in ('acoustic_accompaniment','electric_accompaniment','electric_melody','vocal_melody'):
self.assertEqual(production.dependencies(role,resources),production.dependencies(role,changed))
self.assertNotEqual(production.dependencies('acoustic_solo',resources),production.dependencies('acoustic_solo',changed))
def test_cross_bar_arrival_cell_remains_one_sounding_duration(self):
cell=next(c for c in vocabulary.rhythm_cells(120,'arrival') if c.id=='anticipated_sustain')
self.assertTrue(any(a<4<b for a,b in cell.pattern))
def test_shared_provisional_arrival_preserves_terminal_hold(self):
a=note(0,1,'c',event_id='a');b=note(1,2,'c',event_id='b');c=note(2,4,'e',event_id='c')
t=lambda id,start,end,operation,events:types.Transformation(id,'source','home',operation,F(start),F(end),events,(),preserves=())
draft=types.MelodicDraft('draft',F(),F(4),(a,b,c),(t('a',0,1,'introduce',('a',)),t('b',1,4,'continue',('b','c'))),(),(),(),None,'continue')
h=harmonic.Harmony(choices(('CM7',)))
revised,edits=gesture_rhythm.shared_arrival(draft,h)
self.assertEqual(len(revised.notes),2)
self.assertEqual(revised.notes[0].start,0)
self.assertEqual(revised.notes[-1],c)
self.assertEqual(edits[0].kind,'shared_arrival')
self.assertEqual(gesture_rhythm.revise(draft,h)[1][0].kind,'shared_arrival')
protected=dataclasses.replace(draft,protected=('a',))
self.assertEqual(gesture_rhythm.shared_arrival(protected,h)[0],protected)
if __name__=='__main__':unittest.main()