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.16.tar.gz (12.8 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.16-py3-none-any.whl (939.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tonal-0.0.16.tar.gz
  • Upload date:
  • Size: 12.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for tonal-0.0.16.tar.gz
Algorithm Hash digest
SHA256 702418a2e1e981036d04b31e396aca3b3134e79310e90572852fe94f95f22d7d
MD5 c42b3c62680ce450409a60656cd703d1
BLAKE2b-256 5b6fa51c544a49c6532f9612ed1eb46a8f1f61bc54c8525cf9257cb4f8b19a07

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tonal-0.0.16-py3-none-any.whl
  • Upload date:
  • Size: 939.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for tonal-0.0.16-py3-none-any.whl
Algorithm Hash digest
SHA256 d3008d6d8acf2ce3fcf4f7028646a94482ea8b14955c7ec54c7bf4c9f91dc8d4
MD5 7c7ed6e9ea5428656011e57ae4ab846a
BLAKE2b-256 b12929a9e44cb114e71f209874217dfb5df06c35d89144a9266fc845cf8b24e7

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