Source code for musicscore.tuplet

from typing import Any, Optional

from musicscore.exceptions import TupletNormalTypeError
from musicxml import XMLTimeModification, XMLTuplet

TUPLETACTUALTONORMALNOTES = {
    3: 2,
    5: 4,
    6: 4,
    7: 4,
    9: 8,
    10: 8,
    11: 8,
    12: 8,
    13: 8,
    14: 8,
    15: 8,
}
TUPLETNORMALTYPES = {8: "32nd", 4: "16th", 2: "eighth", 1: "quarter", 0.5: "half"}


[docs]class Tuplet: def __init__( self, actual_notes=3, normal_notes=None, normal_type=None, bracket_type=None, bracket_number=None, quarter_duration=1, ): self._actual_notes = None self._normal_notes = None self._normal_type = None self._bracket_type = None self._bracket_number = None self._quarter_duration = None self.actual_notes = actual_notes self.normal_notes = normal_notes self.normal_type = normal_type self.bracket_type = bracket_type self.bracket_number = bracket_number self.quarter_duration = quarter_duration @property def actual_notes(self) -> int: return self._actual_notes @actual_notes.setter def actual_notes(self, val): if not isinstance(val, int): raise TypeError if val < 2: raise ValueError self._actual_notes = val @property def normal_notes(self) -> int: if self._normal_notes is None: return TUPLETACTUALTONORMALNOTES.get(self.actual_notes) return self._normal_notes @normal_notes.setter def normal_notes(self, val): if val is not None: if not isinstance(val, int): raise TypeError if val < 2: raise ValueError self._normal_notes = val @property def normal_type(self) -> str: if self._normal_type is None: try: return TUPLETNORMALTYPES[self.normal_notes / self.quarter_duration] except KeyError: raise TupletNormalTypeError( f"Cannot find normal type of normal_notes {self.normal_notes} with quarter_duration {self.quarter_duration}. You can set normal_type manually." ) return self._normal_type @normal_type.setter def normal_type(self, val): permitted = [ None, "1024th", "512th", "256th", "128th", "64th", "32nd", "16th", "eighth", "quarter", "half", "whole", "breve", "long", "maxima", ] if val not in permitted: raise ValueError(f"Permitted type values are: {permitted}") self._normal_type = val @property def bracket_type(self) -> Optional[str]: return self._bracket_type @bracket_type.setter def bracket_type(self, val): permitted = [None, "start", "stop"] if val not in permitted: raise ValueError(f"Permitted bracket_type values are: {permitted}") self._bracket_type = val @property def bracket_number(self) -> int: if self._bracket_number is None and self.bracket_type: return 1 return self._bracket_number @bracket_number.setter def bracket_number(self, val): if val is not None: if not isinstance(val, int): raise TypeError if val < 1: raise ValueError self._bracket_number = val @property def ratio(self): return (self.actual_notes, self.normal_notes)
[docs] def get_xml_time_modification(self) -> "XMLTimeModification": output = XMLTimeModification() output.xml_actual_notes = self.actual_notes output.xml_normal_notes = self.normal_notes output.xml_normal_type = self.normal_type return output
[docs] def get_xml_tuplet(self) -> XMLTuplet: if self.bracket_type: output = XMLTuplet(type=self.bracket_type, number=self.bracket_number) if self.bracket_type == "start": output.bracket = "yes" return output
[docs]class SimplifiedSextuplets: _ATTRIBUTES = {"simplified_sextuplets"} def __init__( self, simplified_sextuplets: Optional[bool] = None, *args: Any, **kwargs: Any ) -> None: super().__init__(*args, **kwargs) self._simplified_sextuplets = None self.simplified_sextuplets = simplified_sextuplets @property def simplified_sextuplets(self) -> bool: if self._simplified_sextuplets is None: if self.up: return self.up.simplified_sextuplets else: return False return self._simplified_sextuplets @simplified_sextuplets.setter def simplified_sextuplets(self, value: bool) -> None: self._simplified_sextuplets = value