"""Wrapper functions for input interface."""
from pathlib import Path
from typing import List, TextIO, Union
from mido import MidiFile
from music21.stream import Stream
from numpy import ndarray
from pretty_midi import PrettyMIDI
from pypianoroll import Multitrack
from ..classes import Track
from ..music import Music
from .abc import read_abc
from .event import from_event_representation
from .json import load_json
from .midi import from_mido, from_pretty_midi, read_midi
from .music21 import from_music21
from .musicxml import read_musicxml
from .note import from_note_representation
from .pianoroll import from_pianoroll_representation, from_pypianoroll
from .pitch import from_pitch_representation
from .yaml import load_yaml
[docs]def load(path: Union[str, Path, TextIO], kind: str = None, **kwargs) -> Music:
"""Load a JSON or a YAML file into a Music object.
This is a wrapper function for :func:`muspy.load_json` and
:func:`muspy.load_yaml`.
Parameters
----------
path : str, Path or TextIO
Path to the file or the file to to load.
kind : {'json', 'yaml'}, optional
Format to save. Defaults to infer from the extension.
**kwargs
Keyword arguments to pass to :func:`muspy.load_json` or
:func:`muspy.load_yaml`.
Returns
-------
:class:`muspy.Music`
Loaded Music object.
See Also
--------
:func:`muspy.load_json` : Load a JSON file into a Music object.
:func:`muspy.load_yaml` : Load a YAML file into a Music object.
:func:`muspy.read` :
Read a MIDI/MusicXML/ABC file into a Music object.
"""
if kind is None:
if not isinstance(path, (str, Path)):
raise ValueError("Cannot infer file format from a file object.")
path_str = str(path).lower()
if path_str.endswith((".json", ".json.gz")):
kind = "json"
elif path_str.endswith((".yaml", ".yml", ".yaml.gz", ".yml.gz")):
kind = "yaml"
else:
raise ValueError(
"Cannot infer file format from the extension (expect JSON or "
"YAML)."
)
if kind.lower() == "json":
return load_json(path, **kwargs)
if kind.lower() == "yaml":
return load_yaml(path, **kwargs)
raise ValueError(
f"Expect `kind` to be 'json' or 'yaml', but got : {kind}."
)
[docs]def read(
path: Union[str, Path], kind: str = None, **kwargs
) -> Union[Music, List[Music]]:
"""Read a MIDI/MusicXML/ABC file into a Music object.
Parameters
----------
path : str or Path
Path to the file to read.
kind : {'midi', 'musicxml', 'abc'}, optional
Format to save. Defaults to infer from the extension.
**kwargs
Keyword arguments to pass to :func:`muspy.read_midi`,
:func:`muspy.read_musicxml` or :func:`read_abc`.
Returns
-------
:class:`muspy.Music` or list of :class:`muspy.Music`
Converted Music object(s).
See Also
--------
:func:`muspy.load` : Load a JSON or a YAML file into a Music object.
"""
if kind is None:
if str(path).lower().endswith((".mid", ".midi")):
kind = "midi"
elif str(path).lower().endswith((".mxl", ".xml", ".musicxml")):
kind = "musicxml"
elif str(path).lower().endswith(".abc"):
kind = "abc"
else:
raise ValueError(
"Cannot infer file format from the extension (expect MIDI, "
"MusicXML or ABC)."
)
if kind.lower() == "midi":
return read_midi(path, **kwargs)
if kind.lower() == "musicxml":
return read_musicxml(path, **kwargs)
if kind.lower() == "abc":
return read_abc(path, **kwargs)
raise ValueError(
f"Expect `kind` to be 'midi', 'musicxml' or 'abc', but got : {kind}."
)
[docs]def from_object(
obj: Union[Stream, MidiFile, PrettyMIDI, Multitrack], **kwargs
) -> Union[Music, List[Music], Track, List[Track]]:
"""Return an outside object as a Music object.
Parameters
----------
obj
Object to convert. Supported objects are `music21.Stream`,
:class:`mido.MidiTrack`, :class:`pretty_midi.PrettyMIDI`, and
:class:`pypianoroll.Multitrack` objects.
**kwargs
Keyword arguments to pass to :func:`muspy.from_music21`,
:func:`muspy.from_mido`, :func:`from_pretty_midi` or
:func:`from_pypianoroll`.
Returns
-------
:class:`muspy.Music`
Converted Music object.
"""
if isinstance(obj, Stream):
return from_music21(obj, **kwargs)
if isinstance(obj, MidiFile):
return from_mido(obj, **kwargs)
if isinstance(obj, PrettyMIDI):
return from_pretty_midi(obj, **kwargs)
if isinstance(obj, Multitrack):
return from_pypianoroll(obj, **kwargs)
raise TypeError(
"`obj` must be of type music21.Stream, mido.MidiFile, "
"pretty_midi.PrettyMIDI or pypianoroll.Multitrack."
)
[docs]def from_representation(array: ndarray, kind: str, **kwargs) -> Music:
"""Update with the given representation.
Parameters
----------
array : :class:`numpy.ndarray`
Array in a supported representation.
kind : str, {'pitch', 'pianoroll', 'event', 'note'}
Data representation.
**kwargs
Keyword arguments to pass to
:func:`muspy.from_pitch_representation`,
:func:`muspy.from_pianoroll_representation`,
:func:`from_event_representation` or
:func:`from_note_representation`.
Returns
-------
:class:`muspy.Music`
Converted Music object.
"""
if kind.lower() in ("pitch", "pitch-based"):
return from_pitch_representation(array, **kwargs)
if kind.lower() in ("pianoroll", "piano-roll", "piano roll"):
return from_pianoroll_representation(array, **kwargs)
if kind.lower() in ("event", "event-based"):
return from_event_representation(array, **kwargs)
if kind.lower() in ("note", "note-based"):
return from_note_representation(array, **kwargs)
raise ValueError(
"Expect `kind` to be 'pitch', 'pianoroll', 'event' or 'note', but"
f"got : {kind}."
)