Source code for neoscore.western.meter

from __future__ import annotations

from dataclasses import dataclass
from functools import reduce
from typing import List, Tuple, Union, cast

from typing_extensions import TypeAlias

_glyph_names = {
    0: "timeSig0",
    1: "timeSig1",
    2: "timeSig2",
    3: "timeSig3",
    4: "timeSig4",
    5: "timeSig5",
    6: "timeSig6",
    7: "timeSig7",
    8: "timeSig8",
    9: "timeSig9",
}


[docs]@dataclass(frozen=True) class Meter: """A time signature graphical meter comprising two lists of glyphs. Users are recommended to use the ``Meter.numeric()`` constructor, which provides a convenient way to create standard meters. The direct constructor is mostly useful for writing more exotic meters, supporting arbitrary glyphs. If only a single line of text is needed for the meter (as with the common time "C"), it should go in ``upper_text_glyph_names`` and ``lower_text_glyph_names`` should be left empty. """ upper_text_glyph_names: List[str] lower_text_glyph_names: List[str]
[docs] @classmethod def numeric(cls, upper: Union[int | List[int]], lower: int) -> Meter: """Create a meter with upper and lower numbers. The upper number can be a single number, or a list of them. Lists of numbers will be treated as additive time signatures where each upper number is joined by a plus sign. This is useful for time signatures like ``[3 + 2 + 3] / 8``. """ if isinstance(upper, int): upper_glyphs = Meter._glyphs_for_number(upper) else: upper_glyphs = reduce( lambda a, b: a + ["timeSigPlus"] + b, [Meter._glyphs_for_number(number) for number in upper], ) lower_glyphs = Meter._glyphs_for_number(lower) return Meter(upper_glyphs, lower_glyphs)
[docs] @classmethod def from_def(cls, meter_def: MeterDef) -> Meter: if isinstance(meter_def, tuple): return Meter.numeric(*meter_def) return cast(Meter, meter_def)
@staticmethod def _glyphs_for_number(number: int) -> List[str]: return [_glyph_names[int(digit)] for digit in str(number)]
COMMON_TIME = Meter(["timeSigCommon"], []) CUT_TIME = Meter(["timeSigCutCommon"], []) MeterDef: TypeAlias = Union[Meter, Tuple[Union[int, List[int]], int]] """Shorthand for Meter. Either a Meter, or an argument tuple for ``Meter.numeric``. """