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.18.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.18-py3-none-any.whl (930.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for tonal-0.0.18.tar.gz
Algorithm Hash digest
SHA256 409ccbedd780113afe9d861edf6ce83a6bf1882ff5aa91a49082c53dbe8f7f82
MD5 0f092539b381b99e80fd2f8f0412c15d
BLAKE2b-256 6dbbd54b0e95949e37e0c39dbcda2983235b16c55249328ad28221ca53dc4d02

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for tonal-0.0.18-py3-none-any.whl
Algorithm Hash digest
SHA256 f1b07a03c35fdf9b6c683d1c79a4f60a817449c50cd54755d13427703302a8ab
MD5 76e570c653785e6b8937a710a661fc08
BLAKE2b-256 4b7302b2b0b3e4058eef2229107ca84774ad9c7eae4c5a31617d0f2fa5ec6b7e

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