Module music_df.xml_parser.objects

Classes

class DFItem
Expand source code
@dataclass
class DFItem:
    def asdict(self):
        out = asdict(self)
        out["type"] = self._type
        return out

    def copy(self):
        return copy(self)

DFItem()

Subclasses

Methods

def asdict(self)
Expand source code
def asdict(self):
    out = asdict(self)
    out["type"] = self._type
    return out
def copy(self)
Expand source code
def copy(self):
    return copy(self)
class Measure (onset: t.Optional[Fraction] = None, release: t.Optional[Fraction] = None)
Expand source code
@dataclass
class Measure(DFItem):
    _type = "bar"
    onset: t.Optional[Fraction] = None
    release: t.Optional[Fraction] = None
    # TODO: (Malcolm 2024-08-10) remove
    # expected_duration: t.Optional[Fraction] = None

    # @property
    # def expected_release(self):
    #     assert self.onset is not None and self.expected_duration is not None
    #     return self.onset + self.expected_duration

Measure(onset: 't.Optional[Fraction]' = None, release: 't.Optional[Fraction]' = None)

Ancestors

Instance variables

var onset : fractions.Fraction | None
var release : fractions.Fraction | None
class Note (pitch: t.Optional[int] = None,
onset: t.Optional[Fraction] = None,
release: t.Optional[Fraction] = None,
tie_to_next: bool = False,
tie_to_prev: bool = False,
grace: bool = False,
voice: t.Optional[str] = None,
part: t.Optional[str] = None,
spelling: t.Optional[str] = None,
instrument: t.Optional[str] = None,
midi_instrument: t.Optional[str] = None,
unpitched: bool = False)
Expand source code
@dataclass
class Note(DFItem):
    pitch: t.Optional[int] = None
    onset: t.Optional[Fraction] = None
    release: t.Optional[Fraction] = None
    tie_to_next: bool = False
    tie_to_prev: bool = False
    grace: bool = False
    # We can use voice, when available, to differentiate ties
    voice: t.Optional[str] = None
    part: t.Optional[str] = None
    spelling: t.Optional[str] = None
    instrument: t.Optional[str] = None
    midi_instrument: t.Optional[str] = None
    unpitched: bool = False

    _type = "note"

    def is_valid(self) -> bool:
        if self.onset is None:
            return False
        if (self.pitch is None) and not (self.unpitched):
            return False
        return self.release is not None or self.grace

    @property
    def dur(self) -> Fraction:
        if self.release is None:
            return None
        return (self.release - self.onset).limit_denominator(LIMIT_DENOMINATOR)

    @dur.setter
    def dur(self, val: Fraction):
        self.release = (self.onset + val).limit_denominator(LIMIT_DENOMINATOR)

    def copy(self, remove_ties: bool = False) -> Note:
        out = copy(self)
        if remove_ties:
            out.tie_to_next = False
            out.tie_to_prev = False
        return out

    def set_spelling(
        self,
        step: str,
        alter: int,
        chromatic_transpose: None | int,
        diatonic_transpose: None | int,
    ):
        if alter < 0:
            acc = -alter * "-"
        else:
            acc = alter * "#"
        spelling = step + acc
        if chromatic_transpose is not None:
            assert diatonic_transpose is not None
            spelling = transpose_spelling(
                [spelling],
                chromatic_steps=chromatic_transpose,
                diatonic_steps=diatonic_transpose,
                flat_char="-",
            )[0]
        self.spelling = spelling

    def __str__(self):
        init_tie = "⌒" if self.tie_to_prev else ""
        end_tie = "⌒" if self.tie_to_next else ""
        return f"{init_tie}{self.pitch}:{self.onset}-{self.release}{end_tie}"

Note(pitch: 't.Optional[int]' = None, onset: 't.Optional[Fraction]' = None, release: 't.Optional[Fraction]' = None, tie_to_next: 'bool' = False, tie_to_prev: 'bool' = False, grace: 'bool' = False, voice: 't.Optional[str]' = None, part: 't.Optional[str]' = None, spelling: 't.Optional[str]' = None, instrument: 't.Optional[str]' = None, midi_instrument: 't.Optional[str]' = None, unpitched: 'bool' = False)

Ancestors

Instance variables

prop dur : Fraction
Expand source code
@property
def dur(self) -> Fraction:
    if self.release is None:
        return None
    return (self.release - self.onset).limit_denominator(LIMIT_DENOMINATOR)
var grace : bool
var instrument : str | None
var midi_instrument : str | None
var onset : fractions.Fraction | None
var part : str | None
var pitch : int | None
var release : fractions.Fraction | None
var spelling : str | None
var tie_to_next : bool
var tie_to_prev : bool
var unpitched : bool
var voice : str | None

Methods

def copy(self, remove_ties: bool = False) ‑> Note
Expand source code
def copy(self, remove_ties: bool = False) -> Note:
    out = copy(self)
    if remove_ties:
        out.tie_to_next = False
        out.tie_to_prev = False
    return out
def is_valid(self) ‑> bool
Expand source code
def is_valid(self) -> bool:
    if self.onset is None:
        return False
    if (self.pitch is None) and not (self.unpitched):
        return False
    return self.release is not None or self.grace
def set_spelling(self,
step: str,
alter: int,
chromatic_transpose: None | int,
diatonic_transpose: None | int)
Expand source code
def set_spelling(
    self,
    step: str,
    alter: int,
    chromatic_transpose: None | int,
    diatonic_transpose: None | int,
):
    if alter < 0:
        acc = -alter * "-"
    else:
        acc = alter * "#"
    spelling = step + acc
    if chromatic_transpose is not None:
        assert diatonic_transpose is not None
        spelling = transpose_spelling(
            [spelling],
            chromatic_steps=chromatic_transpose,
            diatonic_steps=diatonic_transpose,
            flat_char="-",
        )[0]
    self.spelling = spelling
class Tempo (onset: Fraction, bpm: float)
Expand source code
@dataclass
class Tempo(DFItem):
    _type = "tempo"
    onset: Fraction
    bpm: float

    def asdict(self):
        return {
            "type": self._type,
            "onset": self.onset,
            "other": {"tempo": self.bpm},
            "release": self.release,
        }

    @property
    def release(self):
        return None

Tempo(onset: 'Fraction', bpm: 'float')

Ancestors

Instance variables

var bpm : float
var onset : fractions.Fraction
prop release
Expand source code
@property
def release(self):
    return None

Methods

def asdict(self)
Expand source code
def asdict(self):
    return {
        "type": self._type,
        "onset": self.onset,
        "other": {"tempo": self.bpm},
        "release": self.release,
    }
class Text (onset: Fraction, content: str)
Expand source code
@dataclass
class Text(DFItem):
    _type = "text"
    onset: Fraction
    content: str

    def asdict(self):
        return {
            "type": self._type,
            "onset": self.onset,
            "other": {"text": self.content},
            "release": self.release,
        }

    @property
    def release(self):
        return None

Text(onset: 'Fraction', content: 'str')

Ancestors

Instance variables

var content : str
var onset : fractions.Fraction
prop release
Expand source code
@property
def release(self):
    return None

Methods

def asdict(self)
Expand source code
def asdict(self):
    return {
        "type": self._type,
        "onset": self.onset,
        "other": {"text": self.content},
        "release": self.release,
    }
class TimeSignature (onset: Fraction, numer: int, denom: int)
Expand source code
@dataclass
class TimeSignature(DFItem):
    _type = "time_signature"
    onset: Fraction
    numer: int
    denom: int

    def asdict(self):
        # to be consistent with how time-sigs are indicated in midi_parser
        return {
            "type": self._type,
            "onset": self.onset,
            "other": {"numerator": self.numer, "denominator": self.denom},
            "release": self.release,
        }

    @property
    def release(self):
        return None

    @property
    def quarter_duration(self):
        # 4/4: 4 * 4 / 4 = 4
        # 2/4: 2 * 4 / 4 = 2
        # 6/8: 6 * 4 / 8 = 3
        return Fraction(self.numer * 4, self.denom)

TimeSignature(onset: 'Fraction', numer: 'int', denom: 'int')

Ancestors

Instance variables

var denom : int
var numer : int
var onset : fractions.Fraction
prop quarter_duration
Expand source code
@property
def quarter_duration(self):
    # 4/4: 4 * 4 / 4 = 4
    # 2/4: 2 * 4 / 4 = 2
    # 6/8: 6 * 4 / 8 = 3
    return Fraction(self.numer * 4, self.denom)
prop release
Expand source code
@property
def release(self):
    return None

Methods

def asdict(self)
Expand source code
def asdict(self):
    # to be consistent with how time-sigs are indicated in midi_parser
    return {
        "type": self._type,
        "onset": self.onset,
        "other": {"numerator": self.numer, "denominator": self.denom},
        "release": self.release,
    }