Fret Limit
This commit is contained in:
+9
-3
@@ -47,7 +47,7 @@ def chord_positions(requirements: generator.fretboard.ChordRequirements, prune:
|
||||
if len(set(requirements.required) - covered) > len(options) - index:
|
||||
return
|
||||
if index == len(options):
|
||||
if selected and requirements.covers(covered) and (not requirements.basses or min(selected, key=lambda p: p.midi).midi % 12 in requirements.basses):
|
||||
if selected and generator.fretboard.has_fret_anchor(selected) and requirements.covers(covered) and (not requirements.basses or min(selected, key=lambda p: p.midi).midi % 12 in requirements.basses):
|
||||
result.append(tuple(selected))
|
||||
return
|
||||
visit(index + 1, selected, covered)
|
||||
@@ -162,6 +162,9 @@ class EventPlacement:
|
||||
exact: tuple
|
||||
added: tuple[generator.fretboard.TabPosition, ...] = ()
|
||||
|
||||
def playable_choices(choices) -> bool:
|
||||
return all(generator.fretboard.playable_attack((*((position, generator.model.fraction(tone['duration'])) for tone, position in choice.exact), *((position, generator.model.fraction(choice.note['duration'])) for position in choice.added))) for choice in choices)
|
||||
|
||||
def continued_sources(notes):
|
||||
result = {p['tie_from'] for n in notes for p in n['pitches'] if 'tie_from' in p}
|
||||
result.update(f'{n["_continue_from"]}_s{s}' for n in notes if '_continue_from' in n for s, _ in generator.fretboard.STANDARD_TUNING)
|
||||
@@ -210,7 +213,7 @@ def attack_candidates(notes: list[dict], tones: dict[str, GuitarTone], active: d
|
||||
break
|
||||
assignment.update((f'{note["id"]}_s{p.string_number}', p) for p in added)
|
||||
choices.append(EventPlacement(note, tuple((p, exact_positions[p['id']]) for p in note['pitches']), added))
|
||||
if not compatible:
|
||||
if not compatible or not playable_choices(choices):
|
||||
continue
|
||||
cost = voicing_cost(positions, profile, requirements.allowed, melody) if fresh else VoicingCost()
|
||||
yield AttackCandidate(tuple(sorted(assignment.items())), tuple(choices), positions, cost)
|
||||
@@ -220,6 +223,8 @@ def attack_candidates(notes: list[dict], tones: dict[str, GuitarTone], active: d
|
||||
continue
|
||||
assignment = tuple(sorted((*exact, *((f'{chord["id"]}_s{p.string_number}', p) for p in positions)))) if chord else exact
|
||||
choices = tuple(EventPlacement(n, tuple((p, exact_positions[p['id']]) for p in n['pitches']), positions if n is chord else ()) for n in notes)
|
||||
if not playable_choices(choices):
|
||||
continue
|
||||
cost = voicing_cost(shape, profile, requirements.allowed, melody) if fresh else VoicingCost()
|
||||
yield AttackCandidate(assignment, choices, shape, cost)
|
||||
|
||||
@@ -305,7 +310,7 @@ def advance_positions(notes: list[dict], onset: fractions.Fraction, tones: dict[
|
||||
if not result:
|
||||
if not fallback and any(n.get('_harmonize') for n in notes):
|
||||
return advance_positions(notes, onset, tones, states, preserve_strings, True)
|
||||
raise ValueError(f'event {notes[0]["id"]}, onset {onset}: no guitar placement within frets {generator.fretboard.MIN_FRET}-{generator.fretboard.MAX_FRET} and at most {generator.fretboard.MAX_FRET_SPAN} consecutive fret positions; electric chords need a fret <= {generator.fretboard.MAX_ANCHOR_FRET}; held/tied strings must remain fixed')
|
||||
raise ValueError(f'event {notes[0]["id"]}, onset {onset}: no guitar placement; single notes need frets {generator.fretboard.MIN_FRET}-{generator.fretboard.MAX_SINGLE_FRET}; chords need frets {generator.fretboard.MIN_FRET}-{generator.fretboard.MAX_FRET}, an anchor <= {generator.fretboard.MAX_ANCHOR_FRET}, and at most {generator.fretboard.MAX_FRET_SPAN} consecutive fret positions; held/tied strings must remain fixed')
|
||||
return result
|
||||
|
||||
def place_guitar(document: dict) -> None:
|
||||
@@ -338,3 +343,4 @@ def place_guitar(document: dict) -> None:
|
||||
if skipped:
|
||||
logging.getLogger(__name__).warning('%s: %s melody harmonizations kept as single notes; first event %s', document['metadata']['title'], len(skipped), skipped[-1])
|
||||
document['staves'][0]['tablature'] = True
|
||||
generator.fretboard.validate_document(document)
|
||||
|
||||
Reference in New Issue
Block a user