just_intonation module

Classes for Just intonation music theory experiments in Python.

class just_intonation.Chord(*args)

Bases: object

A combination of notes separated by just intervals.

Chords can be constructed several ways. For instance, the major chord can be constructed from a list of (possibly fractional) frequency ratio terms:

>>> Chord(4, 5, 6)
Chord(4, 5, 6)
>>> Chord('4:5:6')
Chord(4, 5, 6)
>>> Chord('1-5/4-3/2')
Chord(4, 5, 6)
>>> Chord('1/1 – 5/4 – 3/2')
Chord(4, 5, 6)

or a list of intervals relative to the root:

>>> Chord(Interval('M3'), Interval('P5'))
Chord(4, 5, 6)
>>> Chord('5/4', '3/2')
Chord(4, 5, 6)
>>> Chord((5, 4), (3, 2))
Chord(4, 5, 6)

Beware the difference:

>>> Chord('4 5 6')
Chord(4, 5, 6)
>>> Chord(Interval(4), Interval(5), Interval(6))
Chord(1, 4, 5, 6)

Intervals are relative to a root, not stacked:

>>> Chord(M3, m3)
Chord(20, 24, 25)

Intervals are sorted and duplicate tones removed:

>>> Chord(4, 6, 5, 6)
Chord(4, 5, 6)

But this does not necessarily mean that the terms are sorted. Intervals can be negative from the root, which produces terms that decrease. (Chords are not assumed to be in “root position” or “normal form”):

>>> Chord(-P5, -M3)
Chord(15, 10, 12)
>>> Chord(-P5, P5)
Chord(6, 4, 9)

Note that the order of terms is backwards for Chords vs Intervals:

>>> Chord(Interval(3, 2))
Chord(2, 3)
>>> Chord(Interval(5, 4), Interval(6, 4))
Chord(4, 5, 6)

(This is potentially confusing, but is the way they are typically represented. It may be changed in the future.)

The terms, intervals from root, and intermediate stacked steps of the Chord can be accessed:

>>> Chord(M3, P5).terms
(4, 5, 6)
>>> Chord(4, 5, 6).intervals
(Interval(5, 4), Interval(3, 2))
>>> Chord(4, 5, 6).steps
(Interval(5, 4), Interval(6, 5))
>>> Chord(4, 5, 6).all_steps
{Interval(5, 4), Interval(6, 5), Interval(3, 2)}

as well as the limits:

>>> Chord(20, 25, 30, 36).odd_limit
25
>>> Chord(20, 25, 30, 36).prime_limit
5

Musical inversion moves the lowest tone an octave higher:

>>> Chord(4, 5, 6).inversion(1)
Chord(5, 6, 8)
>>> Chord(4, 5, 6).inversion(2)
Chord(3, 4, 5)

Negating a chord makes all the intervals negative relative to the root (converting it from the otonal overtone series to the utonal undertone series):

>>> -Chord(1, 2, 3)
Chord(6, 2, 3)
>>> Chord('1/1 1/2 1/3')
Chord(6, 2, 3)

NOT accepted: (0, 4, 7) equal temperament notation for major chord. (The 4th note of what scale?)

property all_steps

Set of all music intervals that can be made by any tone in the chord with any other tone

property intervals

List of musical intervals that make up the chord, relative to the root.

inversion(n)

Return the nth inversion of a chord.

The first inversion moves the root an octave up and uses the next term as the root. The second inversion moves that tone up an octave, etc.

property odd_limit

The highest odd limit of any interval found in the Chord.

So the “dyadic odd-limit”? or intervallic

For example:

>>> Chord('1/1 – 5/4 – 3/2 – 9/5').odd_limit
25

even though

>>> Chord('1/1 – 5/4 – 3/2 – 9/5').intervals
(Interval(5, 4), Interval(3, 2), Interval(9, 5))
>>> Chord('1/1 – 5/4 – 3/2 – 9/5').steps
(Interval(5, 4), Interval(6, 5), Interval(6, 5))

because

>>> Interval('9/5') - Interval('5/4')
Interval(36, 25)
property prime_limit

The highest prime limit of any interval found in the Chord.

“intervallic limit”

‘Whether Partch used the word “limit” to refer to odd or prime numbers is a matter of some debate.’

‘Odd-limit” is generally considered to be the more important when the context is a consideration of concordance, whereas “prime-limit” is generally the reference in most other cases.’

property steps

List of musical intervals which, stacked together, produce the chord.

property terms

List of terms in the frequency ratio that makes up the chord.

class just_intonation.Interval(numerator, denominator=None)

Bases: object

A just intonation (JI) musical interval; the distance spanned by a dyad.

There are several ways to construct intervals. For instance, the perfect fifth:

>>> Interval(3, 2)
Interval(3, 2)
>>> Interval('3:2')
Interval(3, 2)
>>> Interval('3/2')
Interval(3, 2)

Some abbreviations are also understood:

>>> Interval('P5')
Interval(3, 2)

Intervals are relative distances between pitches on a musical scale (in logarithmic frequency space). Mathematical operations are handled accordingly, so multiplication becomes addition, powers become multiplication, etc.:[1] [2]

>>> Fraction(5, 4) * Fraction(6, 5)
Fraction(3, 2)
>>> Interval(5, 4) + Interval(6, 5)
Interval(3, 2)
>>> Interval(3, 2) - Interval(6, 5)
Interval(5, 4)

So a span of 3 octaves is:

>>> 3 * Interval(2, 1)
Interval(8, 1)

Other operations are supported where they make sense, such as octave reduction of the 5th harmonic, which is found in the 2nd octave:

>>> Interval(5) % Interval('P8')
Interval(5, 4)
>>> Interval(5) // Interval('P8')
2

or the 8th harmonic being 3 octaves above the root

>>> Interval(8) / Interval('P8')
3
>>> Interval(8) / 3
Interval(2, 1)

Complement (musical inversion):

>>> Interval('P8') - Interval(3, 2)
Interval(4, 3)
>>> Interval('P8') - Interval(6, 5)
Interval(5, 3)

Negation (ratio inversion): An interval with a smaller first term is considered to be below the root note instead of above it:

>>> -Interval(3, 2)
Interval(2, 3)

Comparisons:

>>> max(Interval(256, 243), Interval(9, 8))
Interval(9, 8)
>>> Interval(2, 3) < Interval(3, 2)
True
>>> abs(Interval(2, 3)) == Interval(3, 2)
True

Intervals have some properties:

>>> Interval('P5').complement
Interval(4, 3)
>>> Interval(9, 8).odd_limit
9
>>> Interval(9, 8).prime_limit
3

The module also has shortcut variables for the common intervals. For instance, the Pythagorean comma can be calculated as:

>>> P5 * 12 - P8 * 7
Interval(531441, 524288)

References

property benedetti_height

The measure of inharmonicity used by Giovanni Battista Benedetti, which is simply the numerator multiplied by the denominator of the frequency ratio in simplest form.

ref: https://en.xen.wiki/w/Benedetti_height

property complement

Return the musical complement, or inversion, of the interval.

When summed, an interval and its complement produce an octave.

property denominator

Denominator of the frequency ratio.

property kees_height

“The set of JI intervals with Kees semi-height less than or equal to an odd integer q comprises the q odd limit.”

ref: https://en.xen.wiki/w/Kees_semi-height

property numerator

Numerator of the frequency ratio.

property odd_limit

The lowest odd-limit the interval is in; the greatest odd number found in the frequency ratio (after powers of 2 are removed). For instance, the “7 odd-limit” includes 7:6 and 6:5, but not 9:7 or 15:14.

(If this returns 5, then the interval is in the 5 and 7 odd-limits, but not in the 3 odd-limit.)

“generally preferred for the analysis of simultaneous intervals and chords”

property prime_limit

The prime-limit of the interval; the greatest prime factor of the numbers in the interval’s frequency ratio. For instance, the “7-limit” includes 7:6 and 6:5, as well as 9:7 and 15:14.

Generally used for analysis of scales, since intervals with large integers may still have low odd-limit relationships to other notes in the scale even if they are high odd-limit relative to the root.

property tenney_height

The “harmonic distance” function used by James Tenney, also called “Tenney norm”.

ref: http://www.plainsound.org/pdfs/JC&ToH.pdf

property weil_height

“If p/q is a positive rational number reduced to its lowest terms, then the [multiplicative] Weil height is the integer max(p,q).”

ref: https://en.xen.wiki/w/Weil_height

class just_intonation.Pitch(frequency)

Bases: object

A musical pitch, an absolute location in logarithmic frequency space.

Can be summed with intervals to produce other pitches, etc.

Pitches and math on Intervals is defined in logarithmic space. So you cannot do Pitch(440) * 2. You have to do:

>>> Pitch(440) + Interval(2)
Pitch(880)

This may seem like a strange way to do things until you think about it like this:

>>> A440 = Pitch(440)    # 440 Hz 'concert A'
>>> P8 = Interval(2, 1)  # up an octave
>>> A880 = Pitch(880)
>>> A440 + P8 == A880
True

This is consistent with the way math is done on musical scales.

>>> M3 + m3 == P5
True

Pitches try to have exact Fraction frequency if possible:

>>> Pitch(100) + Interval('M2')
Pitch('225/2')
>>> Pitch(100*9/8)
Pitch(112.5)

The distance between two pitches is an interval:

>>> Pitch(440) - Pitch(330)
Interval(4, 3)
>>> Pitch(440) - Interval(4, 3)
Pitch(330)
property frequency

Frequency of the pitch in hertz.