Skip to main content

Tools for music analysis and generation

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tonal-0.0.19.tar.gz (9.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tonal-0.0.19-py3-none-any.whl (930.3 kB view details)

Uploaded Python 3

File details

Details for the file tonal-0.0.19.tar.gz.

File metadata

  • Download URL: tonal-0.0.19.tar.gz
  • Upload date:
  • Size: 9.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","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}

File hashes

Hashes for tonal-0.0.19.tar.gz
Algorithm Hash digest
SHA256 15e5456cc7f92e42c8a33f849507fb0aeb8932086a295ade5d68788af471900e
MD5 1dfdb438e7b7094a762e0ae2512a6449
BLAKE2b-256 8f24ee4cbb343b5c5fc6fa3b7c4f7e90d5352b1780239ce7eaa827986aca4ab5

See more details on using hashes here.

File details

Details for the file tonal-0.0.19-py3-none-any.whl.

File metadata

  • Download URL: tonal-0.0.19-py3-none-any.whl
  • Upload date:
  • Size: 930.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","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}

File hashes

Hashes for tonal-0.0.19-py3-none-any.whl
Algorithm Hash digest
SHA256 e2e84170e82c1b0e311e96b8f915003122391bfb61c1bae1e002233e894c1277
MD5 8dda65a7faa87a6fc0a8c71961f65eff
BLAKE2b-256 78391d779e216d8f3e2e0c973d4ef6439aef473aa6bcdf0bdba5bd2fb4840454

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page