Midi¶
midi ¶
MIDI numbers, frequencies, and chromatic operations.
The Midi namespace handles conversions between MIDI note numbers
(0-127), note names, and frequencies in Hz. It also exposes lower-level
pitch-class-set helpers used by Pcset and
Scale internally.
The reference frequency is A4 = 440 Hz (MIDI 69). All conversions follow
the standard equal-temperament tuning unless an alternate tuning
argument is provided.
Example
from tonal_py import Midi Midi.to_midi("C4") 60 Midi.midi_to_freq(69) 440.0 Midi.midi_to_note_name(60) 'C4'
Source parity: @tonaljs/midi
is_midi ¶
True if arg (number or numeric string) is in the MIDI range 0-127.
Boolean inputs are rejected. Strings that parse as a number are
accepted (mirrors JS +arg).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arg
|
Any
|
Any value. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True iff |
Example
from tonal_py import Midi Midi.is_midi(60) True Midi.is_midi("60") True Midi.is_midi(128) False Midi.is_midi(-1) False
Source code in src/tonal_py/midi.py
to_midi ¶
Get the MIDI number of a note name or pass through a valid MIDI value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
note
|
str | int | float
|
A note name ( |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
The MIDI number, or |
int | None
|
no MIDI value (pitch class without an octave). |
Example
from tonal_py import Midi Midi.to_midi("C4") 60 Midi.to_midi(60) 60 Midi.to_midi("60") 60 Midi.to_midi("garbage") is None True
Source code in src/tonal_py/midi.py
midi_to_freq ¶
Convert MIDI to frequency in Hz.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
midi
|
float
|
MIDI number (typically 0-127, but any value accepted). |
required |
tuning
|
float
|
Reference frequency for A4. Default 440 Hz. |
440
|
Returns:
| Type | Description |
|---|---|
float
|
Frequency in hertz. |
Example
from tonal_py import Midi Midi.midi_to_freq(69) 440.0 Midi.midi_to_freq(69, tuning=432) # alternate tuning 432.0 round(Midi.midi_to_freq(60), 4) 261.6256
Source code in src/tonal_py/midi.py
freq_to_midi ¶
Convert frequency in Hz to MIDI (with two-decimal precision).
Returns a float rather than int because non-A=440 frequencies
typically don't fall exactly on a MIDI boundary. Rounded to two
decimals using JS-style half-up rounding (not Python's banker's
rounding) for output parity with tonal.js.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
freq
|
float
|
Frequency in hertz. |
required |
Returns:
| Type | Description |
|---|---|
float
|
MIDI number with up to two decimal digits of precision. |
Example
from tonal_py import Midi Midi.freq_to_midi(440) 69.0 Midi.freq_to_midi(220) 57.0 Midi.freq_to_midi(261.62) # close to but not exactly C4 60.0
Source code in src/tonal_py/midi.py
midi_to_note_name ¶
Convert MIDI number to note name. Uses flats by default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
midi
|
float
|
MIDI number. Decimal values are rounded to nearest int. |
required |
options
|
ToNoteNameOptions | None
|
Optional dict with |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The note name (e.g. |
str
|
infinite input. |
Example
from tonal_py import Midi Midi.midi_to_note_name(60) 'C4' Midi.midi_to_note_name(61) # default: flats 'Db4' Midi.midi_to_note_name(61, {"sharps": True}) 'C#4' Midi.midi_to_note_name(61, {"pitchClass": True}) # no octave 'Db' Midi.midi_to_note_name(61.7) # rounds 'D4'
Source code in src/tonal_py/midi.py
chroma ¶
Get the pitch class number 0-11 from a MIDI value.
Example
from tonal_py import Midi Midi.chroma(60) # C 0 Midi.chroma(61) # C#/Db 1 Midi.chroma(72) # C an octave up 0
Source code in src/tonal_py/midi.py
pcset ¶
Get the unique pitch class set from MIDI numbers or a chroma string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
notes
|
list[int] | str
|
Either a list of MIDI numbers (will be deduplicated and
sorted) or a 12-bit chroma string (positions of |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
Sorted list of unique chromas 0-11. |
Example
from tonal_py import Midi Midi.pcset([60, 64, 67, 60, 71]) # C, E, G, C, B (dedup C) [0, 4, 7, 11] Midi.pcset("100100100101") [0, 3, 6, 9, 11]
Source code in src/tonal_py/midi.py
pcset_nearest ¶
Build a function that snaps a MIDI value to the nearest in-set pitch class.
On ties, prefers the higher MIDI (mirrors JS scan order).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
notes
|
list[int] | str
|
Pitch class set (list of MIDI or chroma string). |
required |
Returns:
| Type | Description |
|---|---|
Callable[[int], int | None]
|
A function |
Example
from tonal_py import Midi snap = Midi.pcset_nearest([0, 4, 7]) # C major triad chromas snap(60) # already a C 60 snap(62) # D — equidistant from C and E; tie → E 64
Source code in src/tonal_py/midi.py
pcset_steps ¶
Build a 0-based step-to-MIDI mapper for a pitch class set + tonic.
Step 0 is the tonic; positive steps walk up the set (wrapping octaves as needed); negative steps walk down.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
notes
|
list[int] | str
|
The pitch class set. |
required |
tonic
|
int
|
The starting MIDI value. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[int], int]
|
A function |
Example
from tonal_py import Midi step = Midi.pcset_steps([0, 4, 7], 60) # C major triad, root C4 step(0) 60 step(2) 67 step(3) # wraps to next octave's tonic 72
Source code in src/tonal_py/midi.py
pcset_degrees ¶
Build a 1-based degree-to-MIDI mapper for a pitch class set + tonic.
Like pcset_steps but 1-indexed: degree
1 is the tonic, degree 0 is invalid (returns None).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
notes
|
list[int] | str
|
The pitch class set. |
required |
tonic
|
int
|
The starting MIDI value. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[int], int | None]
|
A function |
Example
from tonal_py import Midi deg = Midi.pcset_degrees([0, 4, 7], 60) deg(1) 60 deg(0) is None # degree 0 invalid in 1-based system True