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 qualityscale_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()
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()
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)
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)
| File | Size | Uploaded | |
|---|---|---|---|
| tonal-0.0.21.tar.gz | 9.5 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|