Skip to main content

tonal

Tools for music analysis and generation

To install: pip install tonal

Examples

notes

The notes module provides tools for working with musical scales, notes, and MIDI data.

Key Concepts

Scale Quality: The characteristic sound or "flavor" of a scale, determined by its specific pattern of intervals (semitones) from the root note. Examples include major, minor, pentatonic, blues, or whole-tone.

Semitone Pattern: A numerical representation of a musical scale, showing the precise distance in semitones (half-steps) of each note from the starting (root) note. For example, the semitone pattern for a major scale is (0, 2, 4, 5, 7, 9, 11).

Working with Scales and MIDI Notes

The scale_midi_notes function converts scale specifications into MIDI note numbers:

from tonal.notes import scale_midi_notes

# Get all C major notes in the middle octave range
notes = scale_midi_notes("C major", midi_range=(60, 72))
print(notes)  # (60, 62, 64, 65, 67, 69, 71, 72)

# Minor pentatonic scale
notes = scale_midi_notes("A minor pentatonic", midi_range=(57, 70))
print(notes)  # (57, 60, 62, 64, 67, 69)

# If no root is specified, defaults to C
notes = scale_midi_notes("dorian", midi_range=(60, 72))
print(notes)  # (60, 62, 63, 65, 67, 69, 70, 72)

Other Utilities

The module also provides:

  • semitone_pattern(quality): Get the semitone intervals for any scale quality
  • scale_params(scale_string): Parse scale strings into root note and quality components
  • Registration functions: Dynamically add new scales, chords, and aliases:
    • register_scale_quality(), register_chord_quality()
    • register_root_note(), register_scale_quality_alias()
  • Listing functions: Explore available musical elements:
    • list_scale_qualities(), list_chord_qualities()
    • list_root_notes(), list_scale_quality_aliases()
from tonal.notes import semitone_pattern, scale_params, list_scale_qualities

# Get the interval pattern for blues scale
pattern = semitone_pattern("blues")
print(pattern)  # (0, 3, 5, 6, 7, 10)

# Parse a scale string
root, quality = scale_params("F# harmonic minor")
print(f"Root: {root}, Quality: {quality}")  # Root: F#, Quality: harmonic minor

# See all available scale qualities
qualities = list_scale_qualities()
print(f"Available scales: {len(qualities)} total")

chords

from tonal import chords_to_wav

chord_sequence = [
    ("Bdim", 120),
    ("Em11", 120),
    ("Amin9", 120),
    ("Dm7", 120),
    "G7",
    "Cmaj7",
]

wav_filepath = chords_to_wav(chord_sequence)

If you have hum you can use it to diplay (and hear) the sound:

from hum import Sound

Sound.from_file(wav_filepath).display()

image

Change the way the chords are played, and what the name (really, filepath) of the midi and wav files produce are.

from tonal.chords import play_arpeggio

Sound.from_file(
    chords_to_wav(chord_sequence, name="test_arpeggio", render_chord=play_arpeggio)
).display()

image

counterpoint

The `translate_in_scale` allows you to translate a sequence of notes, or multiple 
tracks of notes by the given number of steps within the given scale.

>>> stream = translate_in_scale(['C4', 'E4', 'B3', 'C4'], -2, 'C')
>>> stream  # doctest: +ELLIPSIS
<music21.stream.Stream ...>
>>> note_names(stream)
['A3', 'C4', 'G3', 'A3']

For multiple tracks:

>>> tracks = [['C4', 'E4', 'G4'], ['A4', 'C5', 'E5']]
>>> translated_tracks = translate_in_scale(tracks, -2, 'C')
>>> multi_note_names(translated_tracks)
[['A3', 'C4', 'E4'], ['F4', 'A4', 'C5']]

Using some other scales:

With a E major scale:

>>> tracks = [['E4', 'G#4', 'B4'], ['C#5', 'E5', 'G#5']]
>>> translated_tracks = translate_in_scale(tracks, 1, 'E')
>>> multi_note_names(translated_tracks)
[['F#4', 'A4', 'C#5'], ['D#5', 'F#5', 'A5']]

With a D flat major scale:

>>> tracks = [['Db4', 'F4', 'Ab4'], ['Bb4', 'Db5', 'F5']]
>>> translated_tracks = translate_in_scale(tracks, -3, 'Db')
>>> multi_note_names(translated_tracks)
[['A-3', 'C4', 'E-4'], ['F4', 'A-4', 'C5']]

Now let's use a different, "custom" scale, as well as demonstrate the use
of a partial function to get a translator with a fixed input scale:

>>> from functools import partial
>>> from music21.scale import HarmonicMinorScale
>>> translate = partial(
...     translate_in_scale, input_scale='A', scale_creator=HarmonicMinorScale
... )
>>> tracks = [['A4', 'C5', 'E5'], ['G#5', 'A5', 'C6']]
>>> translated_tracks = translate(tracks, 2)
>>> multi_note_names(translated_tracks)
[['C5', 'E5', 'G#5'], ['B5', 'C6', 'E6']]

Let's make a four part cycling V-I progression.

from tonal.counterpoint import translate_in_scale, create_score_from_tracks
from tonal.util import play_music21_object

motif = [
    "C4 C4".split(),
    "E4 E4".split(),
    "G4 F4".split(),
    "B4 A4".split(),
]

tracks = translate_in_scale(motif, range(7, -14, -1), "C")
score = create_score_from_tracks(tracks)
score.show()
play_music21_object(score)
image

Metadata

Release files for tonal 0.0.21

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tonal 0.0.21
File Size Uploaded
tonal-0.0.21.tar.gz 9.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for tonal 0.0.21
File Interpreter ABI Platform
tonal-0.0.21-py3-none-any.whl Python 3 none any Details

Total release size: 10.5 MB

Release files / tonal-0.0.21.tar.gz

Download URL tonal-0.0.21.tar.gz
Size 9.5 MB
Tags Source
SHA-256 checksum
How to use checksums
2f470196fb9a709c892b7be78b385cd64904e497068f81f5b70e4678d685b07c
BLAKE2b-256 checksum
How to use checksums
0621dee61d70f38377aee06c2ef6618442535c058f07e511222c59b2b1ead95f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / tonal-0.0.21-py3-none-any.whl

Download URL tonal-0.0.21-py3-none-any.whl
Size 930.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a5347d85e39d57544a67517f1b79795e90250c5efbade9d1df609929fd2f5f2b
BLAKE2b-256 checksum
How to use checksums
726b88da5fa72838b68d6a05980a97a227b1a2963f04b71492abdfaaa24d9f60
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.0.21 This release

2 release files

0.0.20

2 release files

0.0.19

2 release files

0.0.18

2 release files

0.0.15

2 release files

0.0.14

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page