Source code for neoscore.western.duration_display

from __future__ import annotations

import math
from dataclasses import dataclass

from typing_extensions import TypeAlias

from neoscore.core.math_helpers import is_power_of_2

BaseDuration: TypeAlias = int
"""A base duration used to set notehead and rest glyphs.

Must be 0 or a power of 2. The values correspond to durations like so:

* 0: Double whole note
* 1: Whole note
* 2: Half note
* 4: Quarter note (etc)
"""


[docs]@dataclass(frozen=True) class DurationDisplay: """The basic information about a :obj:`.Duration` needed to write a note with.""" base_duration: BaseDuration dot_count: int def __post_init__(self): if not (is_power_of_2(self.base_duration) or self.base_duration == 0): raise ValueError("base_duration must be 0 or a power of 2") @property def flag_count(self) -> int: """Flag and beam count needed if used in a note""" if self.base_duration <= 4: return 0 return int(math.log2(self.base_duration) - 2) @property def requires_stem(self) -> bool: return self.base_duration > 1