Skip to content

Commit

Permalink
bringing back key_number_to_mido_key_name when creatin mido key signa…
Browse files Browse the repository at this point in the history
…ture (#55)

* bringing back key_number_to_mido_key_name when creatin mido key signatures

* lint fix

* bringing back key_number_to_mido_key_name when creatin mido key signatures

* lint fix
  • Loading branch information
Natooz committed Jun 10, 2024
1 parent 981e8ab commit 4b60081
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
os: [ ubuntu-latest, macOS-latest, windows-latest ]

steps:
Expand Down
27 changes: 27 additions & 0 deletions miditoolkit/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,31 @@
MAJOR_NAMES = ["M", "Maj", "Major", "maj", "major"]
MINOR_NAMES = ["m", "Min", "Minor", "min", "minor"]

KEY_NUMBER_TO_MIDO_KEY_NAME = [
"C",
"Db",
"D",
"Eb",
"E",
"F",
"F#",
"G",
"Ab",
"A",
"Bb",
"B",
"Cm",
"C#m",
"Dm",
"D#m",
"Em",
"Fm",
"F#m",
"Gm",
"G#m",
"Am",
"Bbm",
"Bm",
]

DEFAULT_BPM = 120
17 changes: 10 additions & 7 deletions miditoolkit/midi/containers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

import re
import warnings
from dataclasses import dataclass
from typing import List, Optional, Union

from ..constants import MAJOR_NAMES, MINOR_NAMES

Expand Down Expand Up @@ -232,7 +233,7 @@ class TempoChange:
"""

tempo: Union[float, int]
tempo: float | int
time: int

def __str__(self):
Expand Down Expand Up @@ -273,10 +274,10 @@ def __init__(
program: int,
is_drum: bool = False,
name: str = "",
notes: Optional[List[Note]] = None,
pitch_bends: Optional[List[PitchBend]] = None,
control_changes: Optional[List[ControlChange]] = None,
pedals: Optional[List[Pedal]] = None,
notes: list[Note] | None = None,
pitch_bends: list[PitchBend] | None = None,
control_changes: list[ControlChange] | None = None,
pedals: list[Pedal] | None = None,
):
"""Create the Instrument."""
self.program = program
Expand Down Expand Up @@ -327,7 +328,9 @@ def __eq__(self, other):
return False
if any(
a1 != a2
for a1, a2 in zip(getattr(self, list_attr), getattr(other, list_attr))
for a1, a2 in zip(
getattr(self, list_attr), getattr(other, list_attr), strict=False
)
):
return False

Expand Down
52 changes: 30 additions & 22 deletions miditoolkit/midi/parser.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from __future__ import annotations

import collections
import functools
from collections.abc import Sequence
from pathlib import Path
from typing import List, Optional, Sequence, Tuple, Union

import mido
import numpy as np

from ..constants import DEFAULT_BPM
from ..constants import DEFAULT_BPM, KEY_NUMBER_TO_MIDO_KEY_NAME
from .containers import (
ControlChange,
Instrument,
Expand All @@ -30,7 +32,7 @@
class MidiFile:
def __init__(
self,
filename: Optional[Union[Path, str]] = None,
filename: Path | str | None = None,
file=None,
ticks_per_beat: int = 480,
clip: bool = False,
Expand All @@ -39,12 +41,12 @@ def __init__(
# create empty file
self.ticks_per_beat: int = ticks_per_beat
self.max_tick: int = 0
self.tempo_changes: List[TempoChange] = []
self.time_signature_changes: List[TimeSignature] = []
self.key_signature_changes: List[KeySignature] = []
self.lyrics: List[Lyric] = []
self.markers: List[Marker] = []
self.instruments: List[Instrument] = []
self.tempo_changes: list[TempoChange] = []
self.time_signature_changes: list[TimeSignature] = []
self.key_signature_changes: list[KeySignature] = []
self.lyrics: list[Lyric] = []
self.markers: list[Marker] = []
self.instruments: list[Instrument] = []

# load file
if filename or file:
Expand Down Expand Up @@ -96,7 +98,7 @@ def _convert_delta_to_cumulative(mido_obj: mido.MidiFile):
tick = event.time

@staticmethod
def _load_tempo_changes(mido_obj: mido.MidiFile) -> List[TempoChange]:
def _load_tempo_changes(mido_obj: mido.MidiFile) -> list[TempoChange]:
# default bpm
tempo_changes = [TempoChange(DEFAULT_BPM, 0)]

Expand All @@ -116,7 +118,7 @@ def _load_tempo_changes(mido_obj: mido.MidiFile) -> List[TempoChange]:
return tempo_changes

@staticmethod
def _load_time_signatures(mido_obj: mido.MidiFile) -> List[TimeSignature]:
def _load_time_signatures(mido_obj: mido.MidiFile) -> list[TimeSignature]:
# no default
time_signature_changes = []

Expand All @@ -131,7 +133,7 @@ def _load_time_signatures(mido_obj: mido.MidiFile) -> List[TimeSignature]:
return time_signature_changes

@staticmethod
def _load_key_signatures(mido_obj: mido.MidiFile) -> List[KeySignature]:
def _load_key_signatures(mido_obj: mido.MidiFile) -> list[KeySignature]:
# no default
key_signature_changes = []

Expand All @@ -144,7 +146,7 @@ def _load_key_signatures(mido_obj: mido.MidiFile) -> List[KeySignature]:
return key_signature_changes

@staticmethod
def _load_markers(mido_obj: mido.MidiFile) -> List[Marker]:
def _load_markers(mido_obj: mido.MidiFile) -> list[Marker]:
# no default
markers = []

Expand All @@ -156,7 +158,7 @@ def _load_markers(mido_obj: mido.MidiFile) -> List[Marker]:
return markers

@staticmethod
def _load_lyrics(mido_obj: mido.MidiFile) -> List[Lyric]:
def _load_lyrics(mido_obj: mido.MidiFile) -> list[Lyric]:
# no default
lyrics = []

Expand All @@ -168,7 +170,7 @@ def _load_lyrics(mido_obj: mido.MidiFile) -> List[Lyric]:
return lyrics

@staticmethod
def _load_instruments(midi_data: mido.MidiFile) -> List[Instrument]:
def _load_instruments(midi_data: mido.MidiFile) -> list[Instrument]:
instrument_map = collections.OrderedDict()
# Store a similar mapping to instruments storing "straggler events",
# e.g. events which appear before we want to initialize an Instrument
Expand Down Expand Up @@ -377,7 +379,9 @@ def __eq__(self, other):
return False
if any(
a1 != a2
for a1, a2 in zip(getattr(self, list_attr), getattr(other, list_attr))
for a1, a2 in zip(
getattr(self, list_attr), getattr(other, list_attr), strict=False
)
):
return False

Expand All @@ -386,11 +390,11 @@ def __eq__(self, other):

def dump(
self,
filename: Optional[Union[str, Path]] = None,
filename: str | Path | None = None,
file=None,
segment: Optional[Tuple[int, int]] = None,
segment: tuple[int, int] | None = None,
shift: bool = True,
instrument_idx: Optional[int] = None,
instrument_idx: int | None = None,
charset: str = "latin1",
):
# comparison function
Expand Down Expand Up @@ -499,7 +503,11 @@ def event_compare(event1, event2):
key_list = []
for ks in self.key_signature_changes:
key_list.append(
mido.MetaMessage("key_signature", time=ks.time, key=ks.key_name)
mido.MetaMessage(
"key_signature",
time=ks.time,
key=KEY_NUMBER_TO_MIDO_KEY_NAME[ks.key_number],
)
)

# crop segment
Expand Down Expand Up @@ -704,7 +712,7 @@ def _is_note_within_tick_range(


def _include_meta_events_within_tick_range(
events: Sequence[Union[mido.MetaMessage, mido.Message]],
events: Sequence[mido.MetaMessage | mido.Message],
start_tick: int,
end_tick: int,
shift: bool = False,
Expand Down Expand Up @@ -757,7 +765,7 @@ def _include_meta_events_within_tick_range(
return proc_events


def _get_tick_eq_of_second(sec: Union[float, int], tick_to_time: np.ndarray) -> int:
def _get_tick_eq_of_second(sec: float | int, tick_to_time: np.ndarray) -> int:
return int((np.abs(tick_to_time - sec)).argmin())


Expand Down
18 changes: 10 additions & 8 deletions miditoolkit/pianoroll/parser.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from collections.abc import Callable
from copy import deepcopy
from typing import Callable, List, Optional, Tuple, Union

import numpy as np

Expand All @@ -8,13 +10,13 @@


def notes2pianoroll(
notes: List[Note],
pitch_range: Optional[Tuple[int, int]] = None,
notes: list[Note],
pitch_range: tuple[int, int] | None = None,
pitch_offset: int = 0,
resample_factor: Optional[float] = None,
resample_factor: float | None = None,
resample_method: Callable = round,
velocity_threshold: int = 0,
time_portion: Optional[Tuple[int, int]] = None,
time_portion: tuple[int, int] | None = None,
keep_note_with_zero_duration: bool = True,
) -> np.ndarray:
r"""Converts a sequence of notes into a pianoroll numpy array.
Expand Down Expand Up @@ -120,9 +122,9 @@ def notes2pianoroll(

def pianoroll2notes(
pianoroll: np.ndarray,
resample_factor: Optional[float] = None,
pitch_range: Optional[Union[int, Tuple[int, int]]] = None,
) -> List[Note]:
resample_factor: float | None = None,
pitch_range: int | tuple[int, int] | None = None,
) -> list[Note]:
"""Converts a pianoroll (numpy array) into a sequence of notes.
Args:
Expand Down
38 changes: 19 additions & 19 deletions miditoolkit/pianoroll/vis.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Tuple, Union
from __future__ import annotations

import numpy as np
from matplotlib import pyplot as plt
Expand Down Expand Up @@ -34,20 +34,20 @@
# -------------------------------------------- #
def plot(
pianoroll: np.ndarray,
note_range: Tuple[int, int] = (0, 128),
note_range: tuple[int, int] = (0, 128),
beat_resolution: int = 24,
downbeats: Union[int, np.ndarray] = 4,
downbeats: int | np.ndarray = 4,
background_layout: str = "pianoroll",
grid_layout: str = "x",
xtick: str = "downbeat",
ytick: str = "number",
ytick_interval: int = 12,
xtick_interval: int = 1,
x_range: Optional[Tuple[int, int]] = None,
y_range: Optional[Tuple[int, int]] = None,
figsize: Optional[Tuple[int, int]] = None,
x_range: tuple[int, int] | None = None,
y_range: tuple[int, int] | None = None,
figsize: tuple[int, int] | None = None,
dpi: int = 300,
) -> Tuple[plt.Figure, plt.Axes]:
) -> tuple[plt.Figure, plt.Axes]:
"""Plot Pianoroll
Parameters
----------
Expand Down Expand Up @@ -133,14 +133,14 @@ def plot(
def plot_chroma(
chroma: np.ndarray,
beat_resolution: int = 24,
downbeats: Union[int, np.ndarray] = 4,
downbeats: int | np.ndarray = 4,
xtick: str = "downbeat",
ytick: str = "note",
x_range: Optional[Tuple[int, int]] = None,
x_range: tuple[int, int] | None = None,
xtick_interval: int = 1,
figsize: Optional[Tuple[int, int]] = None,
figsize: tuple[int, int] | None = None,
dpi: int = 300,
) -> Tuple[plt.Figure, plt.Axes]:
) -> tuple[plt.Figure, plt.Axes]:
"""Plot Chromagram
Parameters
----------
Expand Down Expand Up @@ -217,11 +217,11 @@ def plot_chroma(

def plot_heatmap(
to_plot: np.ndarray,
tick_interval: Optional[int] = None,
tick_interval: int | None = None,
origin: str = "upper",
figsize: Optional[Tuple[int, int]] = None,
figsize: tuple[int, int] | None = None,
dpi: int = 300,
) -> Tuple[plt.Figure, plt.Axes]:
) -> tuple[plt.Figure, plt.Axes]:
"""Plot Similarity Matrix
Parameters
----------
Expand Down Expand Up @@ -282,7 +282,7 @@ def plot_grid(ax: plt.Axes, layout: str, which: str = "minor", color="k"):
# always using 'minor' tick to plot grid
# argumens check
if layout not in ["x", "y", "both", None]:
raise ValueError("Unkown Grid layout: %s" % layout)
raise ValueError(f"Unkown Grid layout: {layout}")

# grid Show
if layout in ["x", "both"]:
Expand Down Expand Up @@ -332,7 +332,7 @@ def plot_xticks(
xtick_interval: int,
max_tick: int,
beat_resolution: int,
downbeats: Optional[int] = None,
downbeats: int | None = None,
):
# tick arrangement
# - xtick, minor for beat
Expand All @@ -352,7 +352,7 @@ def plot_xticks(
elif downbeats.dtype == bool:
xticks_downbeats = np.where(downbeats == True) # noqa: E712
else:
raise ValueError("Unkown downbeats type: %s" % downbeats)
raise ValueError(f"Unkown downbeats type: {downbeats}")
ax.set_xticks(xticks_downbeats)
ax.grid(
axis="x", color="k", which="major", linestyle="-", linewidth=0.5, alpha=1.0
Expand Down Expand Up @@ -385,7 +385,7 @@ def plot_xticks(
ax.tick_params(axis="x", which="minor", width=0)
ax.tick_params(axis="x", which="major", width=0)
else:
raise ValueError("Unkown xtick type: %s" % xtick)
raise ValueError(f"Unkown xtick type: {xtick}")


def plot_background(ax: plt.Axes, layout: str, canvas):
Expand All @@ -409,7 +409,7 @@ def plot_background(ax: plt.Axes, layout: str, canvas):
elif layout == "blank":
pass
else:
raise ValueError("Unkown background layout: %s" % layout)
raise ValueError(f"Unkown background layout: {layout}")


def plot_note_entries(ax: plt.Axes, to_plot):
Expand Down
Loading

0 comments on commit 4b60081

Please sign in to comment.