"""Sounding-register references and hard solo instrument domains.""" from __future__ import annotations import dataclasses import fractions import functools import generator.fretboard @dataclasses.dataclass(frozen=True) class Instrument: part: str = '' strings: tuple[int, ...] = (1, 2, 3, 4, 5, 6) reference: int | None = None melody_range: tuple[int, int] | None = None @property def register(self): tuning = [p for s, p in generator.fretboard.STANDARD_TUNING if s in self.strings] return min(tuning) + 1, max(tuning) + 12 @functools.lru_cache(maxsize=4096) def permits(self, number): return any(p.string_number in self.strings for p in generator.fretboard.single_positions_for_pitch(fractions.Fraction(number))) UNRESTRICTED = Instrument() def for_part(part, analysis=None): if part not in ('acoustic', 'electric'): raise ValueError('unknown solo instrument: ' + part) strings = (1, 2, 3, 4, 5, 6) if analysis is None or not analysis.melody: return Instrument(part, strings) return Instrument(part, strings)