+29
-13
@@ -46,7 +46,7 @@ class VoicingTests(unittest.TestCase):
|
||||
def test_root_precedes_physical_cost_without_covering_the_melody(self):
|
||||
self.assertEqual(ranked('CM7', (67,))[0], grip((2, 4, 1, 3)))
|
||||
rooted = generator.guitar.voicing_cost(grip((2, 4, 1, 3)), 'electric', (0, 4, 7, 11), 0, (67,))
|
||||
rootless = generator.guitar.voicing_cost(grip((2, 0, 0, 3)), 'electric', (0, 4, 7, 11), 0, (67,))
|
||||
rootless = generator.guitar.voicing_cost(grip((5, 4, 5, 3)), 'electric', (0, 4, 7, 11), 0, (67,))
|
||||
self.assertGreater(rooted.effort, rootless.effort)
|
||||
self.assertLess(rooted, rootless)
|
||||
def test_essential_extensions_are_never_relaxed_to_add_the_root(self):
|
||||
@@ -68,25 +68,41 @@ class VoicingTests(unittest.TestCase):
|
||||
candidates = list(generator.guitar.attack_candidates([note], tones, {}, {}, False))
|
||||
self.assertTrue(candidates)
|
||||
self.assertTrue(all(c.cost.missing_root == 0 and all(p.midi % 12 != 0 for p in c.shape) for c in candidates))
|
||||
def test_lower_frets_and_small_spans_have_explicit_costs(self):
|
||||
def test_frets_zero_through_twelve_have_no_height_cost(self):
|
||||
for profile in ('', 'electric', 'acoustic'):
|
||||
low = generator.guitar.voicing_cost(grip((3, 3, 3, 3)), profile)
|
||||
high = generator.guitar.voicing_cost(grip((15, 15, 15, 15)), profile)
|
||||
self.assertLess(low, high)
|
||||
self.assertEqual(high.effort - low.effort, 24)
|
||||
for fret in range(13):
|
||||
with self.subTest(profile=profile, fret=fret):
|
||||
self.assertEqual(generator.guitar.voicing_cost(grip((fret,) * 4), profile).effort, 0)
|
||||
self.assertEqual(generator.guitar.voicing_cost((), profile).effort, 0)
|
||||
def test_height_cost_only_counts_frets_above_twelve(self):
|
||||
for profile in ('', 'electric', 'acoustic'):
|
||||
for fret in range(13, 21):
|
||||
with self.subTest(profile=profile, fret=fret):
|
||||
self.assertEqual(generator.guitar.voicing_cost(grip((fret,) * 4), profile).effort, 2 * (fret - 12))
|
||||
crossing = grip((11, 12, 13, 14))
|
||||
self.assertEqual(generator.guitar.voicing_cost(crossing).effort, 7)
|
||||
self.assertEqual(generator.guitar.voicing_cost(crossing, 'acoustic').effort, 19)
|
||||
def test_span_and_acoustic_simplicity_costs_remain_unchanged(self):
|
||||
shape = grip((0, 2, 3, 4))
|
||||
self.assertEqual(generator.guitar.voicing_cost(shape).effort, 12)
|
||||
self.assertEqual(generator.guitar.voicing_cost(shape, 'acoustic').effort, 26)
|
||||
self.assertEqual(generator.guitar.voicing_cost(shape).effort, 4)
|
||||
self.assertEqual(generator.guitar.voicing_cost(shape, 'acoustic').effort, 18)
|
||||
for profile in ('', 'electric', 'acoustic'):
|
||||
self.assertLess(generator.guitar.voicing_cost(grip((8, 8, 8, 8)), profile), generator.guitar.voicing_cost(grip((2, 4, 1, 3)), profile))
|
||||
def test_acoustic_simpler_three_note_shape_can_beat_four_notes(self):
|
||||
candidates = ranked('C7', profile='acoustic')
|
||||
candidates = ranked('C6', profile='acoustic')
|
||||
best = candidates[0]
|
||||
self.assertEqual(len(best), 3)
|
||||
self.assertTrue(any(len(c) == 4 for c in candidates))
|
||||
required, _, _ = generator.guitar.chord_requirements(generator.harmony.parse_symbol('C7'), 'acoustic')
|
||||
required, _, _ = generator.guitar.chord_requirements(generator.harmony.parse_symbol('C6'), 'acoustic')
|
||||
self.assertTrue(set(required) <= {p.midi % 12 for p in best})
|
||||
def test_nearby_position_can_balance_lower_fret_preference(self):
|
||||
low, nearby, previous = (grip((f,), (1,)) for f in (3, 4, 5))
|
||||
self.assertEqual(generator.guitar.voicing_cost(low).moved(generator.guitar.movement(previous, low)), generator.guitar.voicing_cost(nearby).moved(generator.guitar.movement(previous, nearby)))
|
||||
def test_nearby_position_beats_lower_frets_within_comfort_range(self):
|
||||
low, nearby, previous = (grip((f,) * 4) for f in (3, 8, 9))
|
||||
for profile in ('', 'electric', 'acoustic'):
|
||||
self.assertLess(generator.guitar.voicing_cost(nearby, profile).moved(generator.guitar.movement(previous, nearby)), generator.guitar.voicing_cost(low, profile).moved(generator.guitar.movement(previous, low)))
|
||||
def test_above_threshold_is_a_soft_cost_not_a_range_priority(self):
|
||||
low, high = (grip((f,) * 4) for f in (3, 13))
|
||||
for profile in ('', 'electric', 'acoustic'):
|
||||
self.assertLess(generator.guitar.voicing_cost(high, profile), generator.guitar.voicing_cost(low, profile).moved(generator.guitar.movement(high, low)))
|
||||
def test_candidate_pruning_uses_full_cost_and_preserves_each_center(self):
|
||||
for symbol, profile, melody in (('FM7', 'electric', (69,)), ('C7', 'acoustic', ()), ('Gm7', 'electric', (67,))):
|
||||
best = {}
|
||||
|
||||
Reference in New Issue
Block a user