As acold arsenic caller features are concerned, type 0.4.0 is not a step but a leap forward. Xenharmlib’s halfway has been refactored to allow not only equal-division temperaments but besides tunings pinch multiple generator intervals. This intends that it now supports the full range of regular temperaments, including Just Intonation.

With the sole objection of irregular temperaments (such arsenic the “Werckmeister temperaments”), xenharmlib tin yet represent the full cosmos of philharmonic traditions successful mathematical form. It tin now beryllium utilized for the meticulous study of euphony from the Byzantine Empire, the European Renaissance, Indian classical music, the Indonesian gamelan tradition, Arabic Maqam and 20th-century American experimental euphony (such arsenic the compositions of Harry Partch aliases Ben Johnston)

In keeping pinch its holistic approach, xenharmlib allows the use of existing analytical devices for each regular temperaments, provided they are mathematically compatible pinch them. For example, Prime Form and Normal Form calculations tin besides be performed connected (multi-dimensional) regular temperaments.

In addition, the archiving has been wholly revamped: feature examples are organized by tuning and notation, and comprehensive, dedicated archiving is provided for all harmonic primitives. We will springiness a little overview of the aforementioned (and other) features hereinafter. (For the afloat Changelog see here)

Table of Contents

  • Just Intonation / Prime Limit Tunings

  • Custom Regular Temperaments

  • Full Interval Arithmetic

  • Additional Harmonic Primitives

  • Interval Class Vectors

  • Closest Frequency Approximation

Just Intonation / Prime Limit Tunings¶

Just Intonation refers to tunings that are based connected “pure intervals”. A axenic interval is characterized by a fraction of 2 integers, e.g. \(\frac{3}{2}\). Historically, astir tuning systems were based on Just Intonation. It was not until the 18th and 19th hundreds of years that equal temperament systems began to summation wide acceptance in practice. Xenharmlib now introduces support for Just Intonation with the Prime Limit Tuning construct:

from xenharmlib import PrimeLimitTuning limit11 = PrimeLimitTuning(11)

A Pythagorean 12-tone chromatic standard can, for example, now beryllium generated by stacking 5 ascending axenic fifths and 6 descending axenic fifths from the guidelines pitch:

from xenharmlib import PrimeLimitTuning from xenharmlib import periodic pythagorean = PrimeLimitTuning(3) C0 = pythagorean.rs_pitch('1/1') P5 = pythagorean.rs_interval('3/2') iseq_a = pythagorean.interval_seq([P5] * 5) iseq_b = pythagorean.interval_seq([-P5] * 6) chromatic_scale = ( C0.scale(iseq_a) | C0.scale(iseq_b) ).pcs_normalized() print(chromatic_scale)
PrimeLimitPitchScale([1, 256/243, 9/8, 32/27, 81/64, 4/3, 1024/729, 3/2, 128/81, 27/16, 16/9, 243/128], 3-Limit)

Most package programs instrumentality functions for Just Intonation not arsenic a complete arithmetic system, but arsenic a strategy of scalar transposition. In the lawsuit of a transposition by a fifth, for example, a definition of the chromatic standard (such arsenic the 1 mentioned above) is typically used arsenic a basis, and the transposition is understood arsenic a displacement of 7 scale degrees:

for i in range(0, 12): pitch = chromatic_scale[i] result = periodic.scalar_transpose(chromatic_scale, pitch, 7) interval = pitch.interval(result) print(f'{pitch.short_repr} --> {result.short_repr} ({interval.short_repr})')
1 --> 3/2 (3/2) 256/243 --> 128/81 (3/2) 9/8 --> 27/16 (3/2) 32/27 --> 16/9 (3/2) 81/64 --> 243/128 (3/2) 4/3 --> 2 (3/2) 1024/729 --> 512/243 (3/2) 3/2 --> 9/4 (3/2) 128/81 --> 64/27 (3/2) 27/16 --> 81/32 (3/2) 16/9 --> 8/3 (3/2) 243/128 --> 2048/729 (262144/177147)

As you tin spot pinch the past transportation of the output (\(\frac{243}{128}\)), transposition by standard grade successful a Pythagorean chromatic standard does not ever consequence successful an actual transposition of the interval successful question. This is simply a communal problem erstwhile tuning a keyboard instrumentality (such arsenic a piano aliases harpsichord) that has only a constricted number of notes per octave. Mathematically speaking, this meaning of transposition by a 5th is irregular: the size of the 5th changes depending connected which statement is chosen as the starting point.

Unlike a keyboard instrument, a stringed instrumentality without frets aliases the human sound does not person the problem of constricted statement selection. Xenharmlib truthful implements its default transposition not arsenic scalar transposition, but arsenic regular transposition, pinch the effect that the result of transposing the past statement of the supra standard has a pitch class nary longer represented successful the standard itself.

for i in range(0, 12): pitch = chromatic_scale[i] result = pitch.transpose(P5) interval = pitch.interval(result) try: scale_degree = periodic.index(chromatic_scale, result) except ValueError: scale_degree = 'not successful scale' print(f'{pitch.short_repr} --> {result.short_repr} ', end='') print(f'({interval.short_repr}) - degree: {scale_degree}')
1 --> 3/2 (3/2) - degree: 7 256/243 --> 128/81 (3/2) - degree: 8 9/8 --> 27/16 (3/2) - degree: 9 32/27 --> 16/9 (3/2) - degree: 10 81/64 --> 243/128 (3/2) - degree: 11 4/3 --> 2 (3/2) - degree: 12 1024/729 --> 512/243 (3/2) - degree: 13 3/2 --> 9/4 (3/2) - degree: 14 128/81 --> 64/27 (3/2) - degree: 15 27/16 --> 81/32 (3/2) - degree: 16 16/9 --> 8/3 (3/2) - degree: 17 243/128 --> 729/256 (3/2) - degree: not successful scale

This meaning is not only mathematically much sound (since it has a single, accordant meaning of a fifth), but it besides allows america to deal with compositions that usage the disposable tuning abstraction to its full extent, not conscionable a chromatic action of pitches.

Custom Regular Temperaments¶

Custom regular temperaments tin now beryllium designed utilizing the recently introduced Multi-Generator Tunings. The Quarter-Comma-Meantone Temperament that flattens the tritave by a 4th of the syntonic comma can, for example, beryllium constructed for illustration this:

from fractions import Fraction from xenharmlib import MultiGenTuning from xenharmlib import FrequencyRatio g3 = FrequencyRatio(3) * FrequencyRatio(80, 81) ** Fraction(1, 4) qcm = MultiGenTuning( (FrequencyRatio(2), g3), eq_diff_vec=(1, 0) )

Full Interval Arithmetic¶

A characteristic basal for galore theoretical applications — 1 that was long missing from xenharmlib — is now being introduced successful type 0.4.0. We’re talking astir interval arithmetic:

from xenharmlib import WesternNotation western = WesternNotation() m3 = western.shorthand_interval('m', 3) M3 = western.shorthand_interval('M', 3) print(m3 + M3) print(M3 - m3) print(3 * M3)
WesternNoteInterval(P, 5) WesternNoteInterval(A, 1) WesternNoteInterval(A, 7)

To study more, please consult the dedicated page connected intervals.

Additional Harmonic Primitives¶

Version 0.4.0 comes pinch 2 caller harmonic primitives for its analytical toolbox:

Sequences let you to conceptualize a “succession of notes”, for illustration successful conception analysis. Sequences travel pinch emblematic transformation methods for illustration retrograde and inversion.

from xenharmlib import WesternNotation western = WesternNotation() # melodic travel of the opening of "marry had a small lamb" seq = western.seq(western.note(pcs, 4) for pcs in 'EDCDEEE') print(seq) print(seq.retrograde()) print(seq.inversion())
WesternNoteSeq([E4, D4, C4, D4, E4, E4, E4]) WesternNoteSeq([E4, E4, E4, D4, C4, D4, E4]) WesternNoteSeq([E4, F#4, G#4, F#4, E4, E4, E4])

With Interval Fans, a caller type of abstract scale entity is introduced that describes the comparative distances of the elements of a series aliases standard to a tonal center:

from xenharmlib import WesternNotation western = WesternNotation() # melodic travel of the opening of "marry had a small lamb" seq = western.seq(western.note(pcs, 4) for pcs in 'EDCDEEE') # cipher comparative distances to the tonic of C4 tonic = western.note('C', 4) ifan = seq.to_interval_fan(tonic) print(ifan)
WesternNoteIntervalFan([M3, M2, P1, M2, M3, M3, M3])

Interval Class Vectors¶

As an basal instrumentality for standard analysis, particularly successful post-tonal analysis, xenharmlib now supports the calculation of interval people vectors:

from xenharmlib import EDOTuning from xenharmlib.setc import ic_vector edo31 = EDOTuning(31) scale = edo31.index_scale([0, 5, 11, 15, 17, 21]) print(ic_vector(scale))
(0, 1, 0, 2, 1, 3, 0, 0, 0, 3, 1, 1, 0, 1, 2)

Closest Frequency Approximation¶

All harmonic primitives of one-dimensional tunings and notations now support closest wave approximation, e.g. scales:

from xenharmlib import WesternNotation from xenharmlib import Frequency western = WesternNotation() # overtone frequencies measured e.g. by # a spectrogram plugin aliases librosa frequencies = [ Frequency(f) for f in [230, 410, 460, 500, 690] ] scale = western.closest_scale(frequencies) print(scale)
WesternNoteScale([A#3, G#4, A#4, B4, F5])