Source code for musicscore.tuplet

from typing import 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