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

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for tonal-0.0.17.tar.gz
Algorithm Hash digest
SHA256 b6b83a0c3146cc607b0d6f18104e953b2c45290cf34dbedd234302f9658aefdd
MD5 fbe75a5f3aa8f8c033d69dc4c6ccf175
BLAKE2b-256 44292fa60f73fac4ea5d8d1cf76b6244760a36b038387d5c87949604ac5efd4f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tonal-0.0.17-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.19

File hashes

Hashes for tonal-0.0.17-py3-none-any.whl
Algorithm Hash digest
SHA256 3b2a4c3322d59a15afb3ec66ad4e070e4a003ae973d1d3d22a6f4b4bd06e82dd
MD5 59b164cd987f8f774600313926872aed
BLAKE2b-256 8eda5c0656ec95504b59601ff8f79a14b7b1048656ae876171f6ae1e35d3b378

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