Xenharmonic (adj.): Pertaining to music which sounds unlike
that composed in the familiar 12 tone equal-tempered scale.

Ivor Darreg

Xenharmlib is a generalized music theory library that supports traditional
Western and non-western harmonic systems, unconventional microtonal and
macrotonal tunings, diatonic and posttonal set theory and non-standard
notations.

It is easy to use, extendable, and tries to be intuitive. Have a peek:

from xenharmlib import WesternNotation
from xenharmlib.periodic import mod_connectors

n = WesternNotation()

# find out which I-III-V triads can be used
# to modulate between d minor and g major

d_minor = n.pc_scale(['D', 'E', 'F', 'G', 'A', 'Bb', 'C'])
g_major = n.pc_scale(['G', 'A', 'B', 'C', 'D', 'E', 'F#'])

for c in mod_connectors(d_minor, g_major, (0, 2, 4)):
    print(c)
WesternNoteScale([A0, C1, E1])
WesternNoteScale([C1, E1, G1])

from xenharmlib import EDOTuning
from xenharmlib import play
from xenharmlib import UpDownNotation

# create a supermajor 7 chord on vD for an
# equal temperament with 31 notes per octave

edo31 = EDOTuning(31)
n_edo31 = UpDownNotation(edo31)

d_down = n_edo31.note('vD', 4)
SM3 = n_edo31.shorthand_interval('^M', 3)
P5 = n_edo31.shorthand_interval('P', 5)
m7 = n_edo31.shorthand_interval('m', 7)

chord = n_edo31.scale(
   [
      d_down,
      d_down.transpose(SM3),
      d_down.transpose(P5),
      d_down.transpose(m7),
   ]
)
print(chord)
UpDownNoteScale([vD4, F#4, vA4, vC5], 31-EDO)

play(chord, duration=1, play_as_chord=True)


from xenharmlib import EDTuning
from xenharmlib import FrequencyRatio

# analyze group theoretical properties of
# Bohlen-Pierce tunings

bp = EDTuning(13, FrequencyRatio(3))

p1 = bp.pitch(4)
p2 = bp.pitch(18)
i1 = bp.interval(p1, p2)

print(p1.pc_index)
print(p2.pc_index)
print(i1.frequency_ratio)

dist = i1.get_generator_distance(
   bp.pitch(7)
)
print(dist)

Audience & Design Philosophy

Xenharmlib is targeted at composers and researchers who already have
basic knowledge in python programming.

Xenharmlib does not aim to be a score composition tool, sequencer,
or synthesizer (however it is possible to build such things on top of
it). Rather it wants to provide a toolset for exploring different
concepts of harmonic relations with a scientific focus.

Xenharmlib is object-oriented but mostly designed around functional
programming principles: Objects are considered immutable and methods
do not alter internal states but return modified versions of the
original object.

Features

A selection of things supported by xenharmlib:

  • Equal division tunings (e.g. Western, Modern Arabic, Turkish Makam,
    Bohlen-Pierce, Wendy Carlos’ Gamma Scale)

  • Western notation (including interval naming)

  • Up/Down notation (a superset of Western notation)

  • Analysis of intervals, scales, and their relations to one another

  • Group theoretical analysis (integer pitches, pitch classes, etc)

  • Interval sequence pattern matching

  • Modulation suggestions for arbitrary key changes

  • Basic posttonal analysis (normal & prime form calculations, inversion, etc)

Roadmap

A list of planned features (not necessarily in chronological order):

  • Templates for Western music

  • Plugin interface for score rendering backends

  • Advanced posttonal analysis (interval vectors, z-Relations, Forte numbers)

  • Rothenberg propriety and interval matrices

  • MOS scale generation utilities

  • Just Intonation and prime limit tunings

  • Extended Helmholtz-Ellis JI Pitch Notation

  • Odd Limit Tunings

  • Arel-Ezgi-Uzdilek notation

License

Xenharmlib is released under the GNU Public License v3.

You can find the source code hosted on Gitlab.com

Acknowledgments

Thanks to Kite Giedraitis and
Lumi Pakkanen and everyone else on the
Xenharmonic Alliance Discord who was patient with me when I was
struggling to implement UpDownNotation.

Support and Contact

If you want to ask for a new feature or report a bug, take it to the
Gitlab issue page.
In case you just wanna chat with the maintainer: I often hang around on
the Xenharmonic Alliance Discord
under the name @retooth

User Guide

In the following, you will find a guide to most of xenharmlib’s
features.

Contributor Guide

You are always welcome to open a pull request, however, there are some
prerequisites for a pull request to be accepted that you should know:

  • For formatting your commit messages please use
    conventional commits

  • To format your code please use the
    black code formatter
    with string normalization turned off and maximum line length 79.
    In regards to strings, xemharmlib follows the principle single quotes
    (’) for data, double quotes (”) for information meant to be read only
    by humans (like exception descriptions) and triple-double quotes (“””)
    for docstrings.

  • Your code should come with tests that cover everything you have done.
    (This includes branch coverage). Xenharmlib’s test framework is
    pytest

  • Your code should come with type annotations. There are a few
    exceptions: Sometimes python’s typing system is not mature enough to
    do proper static-like typing (for example it doesn’t support
    higher-kinded types). Sometimes there are design reasons to use
    python’s dynamism. Just snoop around the existing code to get a
    feeling for this balance.

  • Xenharmlib is designed around functional programming principles.
    Objects should not alter their state when calling methods (except
    on initialization methods)

Changelog

For a list of changes see Changelog