Core API documentation

Frequency

Frequencies are the prime substance of pitches. Everything in xenharmlib (and in music, for that matter) ultimately boils down to frequencies and their relations to one another. In this module, we implement a couple of useful representations for frequencies and frequency ratios.

class xenharmlib.core.frequencies.Frequency(number: int | Fraction | float | FrequencyRatio)

Frequency is the class to which all pitch definitions ultimately come down. Frequencies represent the physical layer of sound, stripped from all other abstractions.

Frequency is a wrapper around symbolic mathematical expressions that are provided by the sympy package. Using those expressions instead of floats allows us to do exact precision calculations. This is especially useful in regard to equal division tunings where pitches have irrational frequencies.

Frequency objects can be constructed by providing an integer, float, Fraction or a sympy expression. For example

>>> from xenharmlib import Frequency
>>> from fractions import Fraction
>>> Frequency(440)
Frequency(440)
>>> Frequency(1.5)
Frequency(3/2)
>>> Frequency(Fraction(3, 2))
Frequency(3/2)
>>> import sympy as sp
>>> Frequency(sp.Integer(2)**sp.Rational(1, 12))
Frequency(2**(1/12))

As you might have noticed floats get converted to fractions internally. This is done to ensure precision when dealing with frequencies, however despite this safeguard using floats has a lot of pitfalls, as you can see in this example:

>>> Frequency(0.2)
Frequency(3602879701896397/18014398509481984)

For very technical reasons floats are pretty bad at saving certain numbers. So even though it is possible to initialize a Frequency from a float it is highly discouraged. Instead, you should use python’s Fraction type

>>> Frequency(Fraction(2, 10))
Frequency(1/5)
>>> Frequency(440 + Fraction(2, 10))
Frequency(2201/5)

If you want a more human-readable form you can always convert to float after all calculations have been done:

>>> Frequency(440 + Fraction(2, 10)).to_float()
440.2

Frequency objects are part of a dimensionful arithmetic that is defined on Frequency objects and various scalars. Frequencies can interact with one another and with scalar values in the way how they would in a proper physical equation:

Frequencies can be added to and subtracted from other frequencies:

>>> Frequency(440) + Frequency(100)
Frequency(540)
>>> Frequency(440) - Frequency(100)
Frequency(340)

However, the same way as adding a dimensionless quality to a quantity in Hz is forbidden in a physical equation Frequency objects and scalar values can not be added in xenharmlib:

>>> Frequency(440) + 100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Frequency' and 'int'"

For multiplication the same holds in reverse. Frequencies can be multiplied by a scalar, but not with one other:

>>> from xenharmlib import FrequencyRatio
>>> 3 * Frequency(100)
Frequency(300)
>>> Frequency(200) * FrequencyRatio(3, 2)
Frequency(300)

A Frequency can be divided by both a scalar and a frequency. While the first case results in a Frequency in Hz, the second will be a scalar FrequencyRatio without a physical unit attached to it:

>>> Frequency(440) / 10
Frequency(44)
>>> Frequency(440) / Frequency(100)
FrequencyRatio(22/5)

Even though a frequency can be divided by a scalar, the same does not hold in reverse: Dividing a scalar by a frequency will raise an error. Even though an expression like 1 / 80 Hz is technically legal in a physics equation it is outside the scope of this implementation.

>>> 1 / Frequency(100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'int' and 'Frequency'"
get_harmonic(index: int) Frequency

Returns the k-th overtone frequency for this frequency.

Parameters:

index – Index of the harmonic. 0 is the original frequency, 1 the first harmonic, etc

get_harmonics(limit: Frequency | None = None) List[Frequency]

Returns a list of overtone frequencies for this note

Parameters:

limit – (optional) upper-frequency limit of the list in Hz, defaults to the average audible maximum of the human ear of 20KHz

to_float() float

Converts this object into a floating point number

class xenharmlib.core.frequencies.FrequencyRatio(numerator: int | Fraction | float | FrequencyRatio, denominator: int | Fraction | float | FrequencyRatio = 1)

The FrequencyRatio class can be understood as an augmented version of the Python built-in Fraction type. Different from the built-in Fraction type FrequencyRatio can also hold infinite-precision irrational fractions like \(\frac{\sqrt[12]{2}}{2^{\frac{1}{12}}}\) that are essential for equal temperament intervals.

For infinite-precision calculation, FrequencyRatio wraps the sympy package for symbolic arithmetic. Calculation results do not get converted to approximations until the user explicitly decides to.

FrequencyRatio objects can be created like Fractions:

>>> FrequencyRatio(20, 8)
FrequencyRatio(5/2)
>>> FrequencyRatio(3)
FrequencyRatio(3)

For both numerator and denominator, sympy expressions can be used:

>>> import sympy as sp
>>> FrequencyRatio(sp.Integer(3)**sp.Rational(3, 12), sp.sqrt(3))
FrequencyRatio(3**(3/4)/3)

Frequency ratios can also be constructed from prime exponent vectors (monzos):

>>> FrequencyRatio.from_monzo([-11, 7])
FrequencyRatio(2187/2048)

Floats are also supported, however highly discouraged because of the technical limitations of the data type that can lead to surprising and unwanted results:

>>> FrequencyRatio(0.2) # bad
FrequencyRatio(3602879701896397/18014398509481984)
>>> FrequencyRatio(2, 10) # good
FrequencyRatio(1/5)

Frequency ratios define a standard arithmetic and interact seamlessly with other scalar types:

>>> FrequencyRatio(20, 8) * FrequencyRatio(2)
FrequencyRatio(5)
>>> FrequencyRatio(20, 8) + 3
FrequencyRatio(11/2)
>>> 3 + FrequencyRatio(20, 8)
FrequencyRatio(11/2)
>>> from fractions import Fraction
>>> FrequencyRatio(20, 8) * Fraction(8, 20)
FrequencyRatio(1)
>>> Fraction(16, 20) * FrequencyRatio(20, 8)
FrequencyRatio(2)
>>> FrequencyRatio(20) / 10
FrequencyRatio(2)
>>> 5 / FrequencyRatio(20)
FrequencyRatio(1/4)
property cents

The cents equivalent of this frequency ratio

property denominator: FrequencyRatio

The denominator of the ratio

classmethod from_monzo(monzo: List[int])

Creates a frequency ratio from a monzo. A monzo is a list of exponents for the prime numbers, for example, the argument [-1, 1] creates the frequency \(2^{-1} * 3^1\)

log(base: int | Fraction | float | FrequencyRatio) FrequencyRatio

Returns the result of the logarithm of this object

Parameters:

base – The base that should be assumed for calculation

property numerator: FrequencyRatio

The numerator of the ratio

to_float() float

Converts this object into a floating point number

to_monzo()

Factorizes the frequency ratio into a monzo. A monzo is a list of exponents for the prime numbers, for example, the frequency ratio 3/2 creates the monzo [-1, 1], since \(2^{-1} * 3^1 = \frac{3}{2}\)

Origin Context

This module implements the OriginContext class which is the abstract base class for tunings and notations

class xenharmlib.core.origin_context.OriginContext(freq_repr_cls: type[FreqReprT], interval_cls: type[IntervalT], scale_cls: type[ScaleT], interval_seq_cls: type[IntervalSeqT])

OriginContext is the abstract base class for both tunings and notations. It defines a unified interface for collection and interval builder methods as well as an interface for a defined “zero element” which is used as a reference point for other objects.

OriginContext does not define an interface for the builder method of the FreqRepr object (such as pitch or note) as the name and the function signature vary greatly from context to context (e.g. one dimensional tunings demand an integer as construction argument, more-dimensional tunings a vector, notes in periodic tunings mostly demand a string symbol and a base interval index, etc)

diff_interval(pitch_diff: int) IntervalSeqT

Returns an interval the size of a given pitch index difference.

Parameters:

pitch_diff – The pitch index difference

diff_interval_seq(pitch_diffs: Iterable[int] | None = None) IntervalSeqT

Returns an interval sequence from an iterable of pitch index differences, for example:

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> major_chord = edo12.diff_interval_seq([4, 3])
>>> minor_chord = edo12.diff_interval_seq([3, 4])
Parameters:

pitch_diffs – An iterable containing pitch index differences

interval(source: FreqReprT, target: FreqReprT) IntervalT

Returns an interval having the interval type this origin context was configured with

Raises:

IncompatibleOriginContexts – If either source or target have a different origin context than this one

Parameters:
  • source – The source of the interval

  • target – The target of the interval

interval_seq(intervals: Iterable[IntervalT] | None = None) IntervalSeqT

Returns an interval sequence having the interval sequence type this origin context was configured with

Raises:

IncompatibleOriginContexts – If at least one given element has a different origin context than this one

Parameters:

intervals – A list of intervals originating from this context

scale(elements: Iterable[FreqReprT] | None = None) ScaleT

Returns a scale having the scale type this origin context was configured with

Raises:

IncompatibleOriginContexts – If at least one given element has a different origin context than this one

Parameters:

elements – A list of frequency representations originating from this context

abstract property zero_element: FreqReprT

The zero element is a reference point, in one-dimensional tunings it is the element with index 0, in western notation typically C-0, etc

Frequency Representations

This module implements base classes for frequency representations (pitches, notes, etc)

class xenharmlib.core.freq_repr.FreqRepr(origin_context, frequency: Frequency)

FreqRepr is the base class for all frequency representations (pitches, notes, etc). The class implements a total order on the set of all frequency representations (based on the total order of frequency values). It also saves the origin context of the frequency representation (a tuning or notation)

In addition it defines an abstract method for short string representation and a proxy method ‘interval’ which redirects to the interval method of the origin context.

property frequency: Frequency

The frequency of this object

interval(other: Self)

Returns an interval between this frequency representation and another representation of the same origin context.

Parameters:

other – Another frequency representation of the same origin context

property origin_context

The origin context associated with this frequency representation

reflection(axis: Self | None = None) Self

A reflection of this pitch/note across a pitch/note axis. In technical terms the method calculates the interval from this object to the axis and then applies that interval to to the axis.

Parameters:

axis – The element across which this object is reflected (optional, defaults to the zero element of the origin context)

scale(interval_seq)

Returns a scale that starts with this note and continues with the given interval structure

Parameters:

interval_seq – An interval sequence of the same origin context

abstract property short_repr: str

(Must be implemented by subclasses) A shortened representation of this note (to be used in collection objects like scales)

abstractmethod transpose(diff) Self

(Must be implemented by subclasses) Transposes the frequency representation

class xenharmlib.core.freq_repr.SDFreqRepr(origin_context, frequency: Frequency, pitch_index: int)

Base class for single dimensional frequency representation objects. Assumes an integer pitch index in addition to the frequency as part of the data structure.

Implements optimizations on the total order based on pitch index data (if objects originate from same context).

Demands that subclasses implement a transpose method

property pitch_index: int

The pitch index of this object

Scales

This module implements base classes for scales

class xenharmlib.core.scale.PeriodicScale(origin_context, elements: Iterable[FreqReprT] | None = None)

PeriodicScale is the abstract base class for scales that contain frequency representations of periodic tunings / notations. It overwrites the set operations to allow for the ignore_bi_index flag.

It implements the following additional methods:
  • pcs_normalized

  • pcs_intersection

  • is_equivalent

  • rotated_up

  • rotated_down

  • rotation

Subclasses must implement at least the transpose function

Parameters:
  • origin_context – An origin context (like a tuning or a notation)

  • elements – A list of frequency representations

difference(other: Self, ignore_bi_index: bool = False) Self

Returns a scale containing only elements from this scale that are NOT present in the other scale

Parameters:
  • other – Another scale of the same origin context

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same. For example, if the difference of two scales including C-0 and C-1 respectively is calculated, C-0 will not be inserted into the new scale

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

intersection(other: Self, ignore_bi_index: bool = False) Self

Returns a new scale including all elements that are included in both scales.

Parameters:
  • other – Another scale of the same origin context

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same. For example, if the intersection of two scales including C-0 and C-1 respectively is calculated, both elements will be added to the result

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

is_disjoint(other: Self, ignore_bi_index: bool = False) bool

Determines if this scale has any common elements with another scale of the same origin context

Parameters:
  • other – Another scale of the same origin context

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same. For example, if one scale includes C-0 and another C-1 the scales will not be considered disjoint

Raises:

IncompatibleOriginContexts – If the other scale originates from a different origin context

is_equivalent(other: PeriodicScale) bool

Deprecated since version 0.3.0: Use is_set_equivalent() instead.

Returns True if two scales are set equivalent, i.e. every element in this scale has an equivalent element somewhere(!) in the other scale (and vice versa).

Periodic scales of different origin contexts can be compared if their origin contexts have the same equivalency interval. Set equivalency between scales of different contexts is defined as “equality after pitch class set normalization”

Raises:

IncompatibleOriginContexts – If the other scale has a different equivalency interval definition

Parameters:

other – Another periodic scale

property is_pcs_normalized: bool

Returns bool if this scale is pcs normalized. A pcs normalized scale only contains elements with base interval index 0.

property is_period_normalized: bool

Returns bool if this scale is period normalized. A period normalized scale only contains elements smaller than the equivalent of the root note, meaning if the scale starts with F3, all subsequent notes are smaller than F4.

property is_plusone_normalized: bool

Returns a period normalized version of the scale with an additional transposed root at the end, e.g. (F0, G0, A0, B0, C1, D1, E1, F1)

is_seq_equivalent(other: PeriodicScale) bool

Returns True if two scales are sequentially equivalent, i.e. every element in this scale corresponds to another one in the other scale at the same scale index.

Periodic scales of different origin contexts can be compared if their origin contexts have the same equivalency interval. Sequential equivalency between scales of different contexts is defined as “equality after base interval alignment”

Raises:

IncompatibleOriginContexts – If the other scale has a different equivalency interval definition

Parameters:

other – Another periodic scale

is_set_equivalent(other: PeriodicScale) bool

Returns True if two scales are set equivalent, i.e. every element in this scale has an equivalent element somewhere(!) in the other scale (and vice versa).

Periodic scales of different origin contexts can be compared if their origin contexts have the same equivalency interval. Set equivalency between scales of different contexts is defined as “equality after pitch class set normalization”

Raises:

IncompatibleOriginContexts – If the other scale has a different equivalency interval definition

Parameters:

other – Another periodic scale

is_subset(other: Self, proper: bool = False, ignore_bi_index: bool = False) bool

Determines if all elements in this scale also exist in the other scale.

Parameters:
  • other – Another scale of the same origin context

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same.

Raises:

IncompatibleOriginContexts – If the other scale originates from a different origin context

is_superset(other: Self, proper: bool = False, ignore_bi_index: bool = False) bool

Determines if all elements in the other scale also exist in this scale.

Parameters:
  • other – Another scale of the same origin context

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same.

Raises:

IncompatibleOriginContexts – If the other scale originates from a different origin context

property is_zp_normalized: bool

Returns bool if the first element is the zero element of the origin context (pitch 0 in tunings, in western-like notations typically C0) and all elements reside in the first base interval.

pcs_intersection(other: Self) Self

Returns a scale including all elements whose pitch class resides in both of the scales, normalized to the first base interval.

Parameters:

other – The other scale

pcs_normalized() Self

Returns a normalized version of this scale where all the elements of the scale are put into the first base interval of the tuning

Note: If the original scale has equivalent element pairs the normalized scale will be smaller in cardinality.

period_normalized() Self

Returns a version of the scale in which each element that is above the root element will be transposed to the interval between the root element and its equivalent in the next base interval. For example the scale of the Fm7/11 chord with notes (F0, Ab0, C1, Eb1, Bb1) will become the scale (F0, Ab0, Bb0, C1, Eb1)

plusone_normalized() Self

Returns a period normalized version of the scale with an additional transposed root at the end, e.g. (F0, G0, A0, B0, C1, D1, E1, F1)

rotated_down() Self

Create a new scale by transposing the base interval of the highest element downwards until it is below the lowest element

rotated_up() Self

Create a new scale by transposing the base interval of the lowest element upwards until it is above the highest element

rotation(order: int) Self

Returns the n-th rotation of this scale.

Parameters:

order – The number of times the scale is rotated. If a negative number is given the scale will be rotated downwards. On 0 the scale will return itself

symmetric_difference(other: Self, ignore_bi_index: bool = False) Self

Returns a scale that includes all the elements from both scales that exist in either of them but NOT BOTH. This is the complement operation of the intersection.

Parameters:
  • other – Another scale of the same origin context

  • ignore_bi_index – (Optional, default False) When set to True elements of the same pitch class will be treated the same. For example, if the difference of two scales including C-0 and C-1 respectively is calculated, C-0 will not be inserted into the new scale

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

transpose_bi_index(bi_diff: int) Self

Returns a scale with the same pitch class indices and symbols, but with a transposed base interval

Parameters:

bi_diff – The difference in base interval between this scale and the resulting one

zp_normalized() Self

Returns the scale transposed in a way so the root has pitch index 0 and all elements reside in the first base interval. In notations with enharmonic ambiguity a designated zero note is used (in western-like notations typically C0)

The function is equivalent to successively invoking zero_normalized + period_normalized or (which is the same) zero_normalized + pcs_normalized

class xenharmlib.core.scale.Scale(origin_context, elements: Iterable[FreqReprT] | None = None)

Scale is the abstract base class for all scale types. The class implements iteration, the ‘in’ operator, the == operator, item retrieval with [] and set operations.

Subclasses must implement at least the transpose function

Parameters:
  • origin_context – An origin context (like a tuning or a notation)

  • elements – A list of frequency representations

difference(other: Self) Self

Returns a scale containing only elements from this scale that are NOT present in the other scale

Parameters:

other – Another scale of the same origin context

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

property frequencies

An ordered list of frequencies present in this scale

intersection(other: Self) Self

Returns a new scale including all elements that are included in both scales.

Parameters:

other – Another scale of the same origin context

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

is_disjoint(other: Self) bool

Determines if this scale has any common elements with another scale of the same origin context.

Parameters:

other – Another scale of the same origin context

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

is_subset(other: Self, proper: bool = False) bool

Determines if all elements in this scale also exist in the other scale.

Parameters:
  • other – Another scale of the same origin context

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

is_superset(other: Self, proper: bool = False) bool

Determines if all elements in the other scale also exist in this scale.

Parameters:
  • other – Another scale of the same origin context

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

abstract property is_zero_normalized: bool

Returns True if this function is zero normalized, meaning that the first element of the scale is identical to the zero element of the origin context (pitch 0 in tunings, typically C0 in western-like notations)

(must be implemented by subclass, since comparison to the the zero note should be done according to notational identity)

property origin_context

The origin context from which this scale was built

partial(mask_expr: int | Tuple[int | EllipsisType, ...]) Self

Returns a new scale consisting of a selection of indices of this scale. The selection is defined by an index mask expression.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a scale including the second, third and sixth element of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the scale, for example (2, …) will select all elements of the scale except the first two.

If only one element should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this scale.

partial_not(mask_expr: int | Tuple[int | EllipsisType, ...]) Self

Returns a new scale consisting of a selection of indices of this scale. The selection will be determined by an index mask and will hold all elements whose index is NOT covered by the mask.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a scale including the second, third and sixth element of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the scale, for example (2, …) will select all elements of the scale except the first two.

If only one element should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this scale.

partition(mask_expr: int | Tuple[int | EllipsisType, ...]) Tuple[Self, Self]

Partitions the scale into two parts using an index mask. The function will return a tuple of two scales with the first scale including all indices that are covered by the index mask and the second one including all indices that are not.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a scale including the second, third and sixth element of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the scale, for example (2, …) will select all elements of the scale except the first two.

If only one element should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this scale.

reflection(axis: FreqReprT | None = None) Self

A reflection of each pitch/note across a pitch/note axis. In technical terms the method calculates the interval from each element to the axis and then applies that interval to to the axis.

Parameters:

axis – The element across which this object is reflected (optional, defaults to the zero element of the origin context)

If scale is reflected across the zero element, reflection is equivalent to inversion of the pitch class set

spec_interval(source_index, target_index)

Returns the specific interval for a generic interval. For example in the 12-EDO C major scale the generic interval defined by (0, 2) is the specific interval major 3.

Parameters:
  • source_index – Source index for the interval

  • target_index – Target index for the interval

symmetric_difference(other: Self) Self

Returns a scale that includes all the elements from both scales that exist in either of them but NOT BOTH. This is the complement operation of the intersection.

Parameters:

other – Another scale of the same origin context

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

to_interval_seq()

Returns this scale represented as an interval sequence

to_intervals() List[Interval[FreqReprT]]

Returns this scale represented as a list of intervals

abstractmethod transpose(diff) Self

Transposes the scale by the given difference (must be overwritten by subclass)

Parameters:

diff – An interval or interval-like object

union(other: Self) Self

Returns a new scale including all elements from this scale as well as the other

Parameters:

other – Another scale of the same origin context

Raises:

IncompatibleOriginContexts – If the other scale has a different origin context

with_element(element: FreqReprT) Self[FreqRepr]

Returns a new scale containing all elements from this scale and the additional one given as a parameter.

Parameters:

element – The new element to be added to the result

Raises:

IncompatibleOriginContexts – If element has a different origin context than this scale

zero_normalized() Self

Returns the scale transposed in a way so the root has pitch index 0. In notations with enharmonic ambiguity a designated zero note is used (in western-like notations typically C0)

Intervals

This module implements base classes for intervals

class xenharmlib.core.interval.Interval(origin_context, frequency_ratio: FrequencyRatio)

Interval is the abstract bass class for all interval types, consisting only of an origin context and a frequency ratio. Based on frequency ratio it implements the cents property and a total ordering.

It forces subclasses to implement the __abs__ method, the class method from_source_and_target and the property short_repr

Parameters:
  • origin_context – An origin context (like a tuning or a notation)

  • frequency_ratio – A frequency ratio object

property cents: float

The interval size in cents (e.g. 1200 for an octave)

property frequency_ratio: FrequencyRatio

The frequency ratio of this interval (e.g. 2 for an octave)

abstractmethod classmethod from_source_and_target(source: FreqReprT, target: FreqReprT) Self

Constructs an interval from two frequency representations (must be implemented by subclass)

Parameters:
  • source – The starting point of the interval

  • target – The end point of the interval

property origin_context

The context this interval originated from (like a tuning or notation)

abstract property short_repr: str

A short string representation of the interval (must be implemented by subclass)

class xenharmlib.core.interval.SDInterval(origin_context, frequency_ratio: FrequencyRatio, pitch_diff: int)

SDInterval (single dimensional interval) extends the Interval class by a pitch_diff property.

Interval Sequences

class xenharmlib.core.interval_seq.IntervalSeq(origin_context, intervals: Sequence[FreqReprT] | None = None)

IntervalSeq is the abstract base class for all interval sequence types. Interval sequences can be understood as “abstract scales” (for example the minor scale as such, instead of C minor). Interval sequences have multiple applications from templating to structure discovery.

In line with its Sequence superclass interval sequences implement iteration, the ‘in’ operator, the == operator, item retrieval with [], concatenation with +, repeated self-concatenation with *, searching with index, and len().

Like scale types interval sequences also allow partitioning with partial, partial_not and partition.

Parameters:
  • origin_context – An origin context (like a tuning or a notation)

  • intervals – A sequence of intervals from the origin context

property cents: List[float]

An ordered list of cent values representing the sequence

property frequency_ratios

An ordered list of frequency ratios present in this sequence

index(interval, start=0, end=None, /) int

Return first index of interval (similar to the index method of python’s list)

Parameters:
  • interval – The interval to search for

  • start – If set method ignores occurences before given index (optional, defaults to 0)

  • end – If set method ignores occurences after given index (optional, defaults to end of sequence)

Raises:

ValueError – If interval was not found in sequence

property origin_context

The origin context from which this interval sequence was built

partial(mask_expr: int | Tuple[int | EllipsisType, ...]) Self

Returns a new sequence consisting of a selection of indices of this sequence. The selection is defined by an index mask expression.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a sequence including the second, third and sixth interval of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the sequence, for example (2, …) will select all intervals of the sequence except the first two.

If only one interval should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this sequence.

partial_not(mask_expr: int | Tuple[int | EllipsisType, ...]) Self

Returns a new sequence consisting of a selection of indices of this sequence. The selection will be determined by an index mask and will hold all intervals whose index is NOT covered by the mask.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) gives a sequence including the second, third and sixth interval of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the sequence, for example (2, …) will select all intervals of the sequence except the first two.

If only one interval should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this sequence.

partition(mask_expr: int | Tuple[int | EllipsisType, ...]) Tuple[Self, Self]

Partitions the sequence into two parts using an index mask. The function will return a tuple of two sequences with the first sequence including all indices that are covered by the index mask and the second one including all indices that are not.

An index mask can be defined as a tuple of consecutive indices, e.g. (1, 2, 5) defines a sequence including the second, third and sixth interval of this one.

An ellipsis between two indices indicates that all indices between them should be selected as well, e.g. (1, …, 5, 9) is equivalent to (1, 2, 3, 4, 5, 9).

If a mask begins with an ellipsis all indices from 0 to the next index are added to the selection, e.g. (…, 3, 5) is equivalent to (0, 1, 2, 3, 5).

A mask without a last index is called right-open and will select all indices from the last index to the end of the sequence, for example (2, …) will select all intervals of the sequence except the first two.

If only one interval should be selected a simple integer can be used

Parameters:

mask_expr – An index mask expression which defines the selection of indices from this sequence.

property pitch_diffs: List[int]

An ordered list of pitch differences representing the sequence

to_scale(start: FreqRepr) Scale

Returns a scale that has the interval structure of this sequence, starting with the given note/pitch

Parameters:

start – A starting note/pitch of the same origin context

with_interval(interval: FreqReprT, insert_pos: int | None = None) Self

Returns a new interval sequence containing all intervals from this sequence and the additional one given as a parameter. By default new intervals appear at the end of the sequence.

Parameters:
  • interval – The new interval to be added to the result

  • insert_pos – The insertion position of the new interval. 0 will insert the interval at the front, 1 will insert the interval at the second position, etc. (optional, default is None which results in the value len(sequence) + 1)

Raises:

IncompatibleOriginContexts – If interval has a different origin context than this sequence

Tuning

A tuning is the middle piece between the continuous world of frequencies and the discrete world of pitch.

In this module, you will find a collection of tuning classes, each with a certain set of assumptions built into them. Some tuning classes can be used as they are to create tuning objects, some are abstract classes that need a couple of methods implemented by a subclass.

class xenharmlib.core.tunings.EDOTuning(divisions, pitch_cls: type[~xenharmlib.core.pitch.EDOPitch] = <class 'xenharmlib.core.pitch.EDOPitch'>, pitch_interval_cls: type[~xenharmlib.core.pitch.EDOPitchInterval] = <class 'xenharmlib.core.pitch.EDOPitchInterval'>, pitch_scale_cls: type[~xenharmlib.core.pitch_scale.EDOPitchScale] = <class 'xenharmlib.core.pitch_scale.EDOPitchScale'>, pitch_interval_seq_cls: type[~xenharmlib.core.pitch_interval_seq.EDOPitchIntervalSeq] = <class 'xenharmlib.core.pitch_interval_seq.EDOPitchIntervalSeq'>, ref_frequency: ~xenharmlib.core.frequencies.Frequency = Frequency(<Mock name='mock.Rational()' id='139200634434576'>))

EDOTuning (“equal division of the octave tuning”) divides an octave into pitches equally spaced from each other.

Parameters:
  • divisions – The number of divisions of the octave

  • pitch_cls – (Optional) The python class for the pitch that is used to generate a pitch object in the pitch method. (Not to be confused with the ‘pitch class’ of pitches in periodic tunings). Defaults to EDOPitch

  • pitch_interval_cls – (Optional) The python class for the pitch interval that is used to generate a pitch interval object in the pitch interval method. Defaults to EDOPitchInterval

  • pitch_scale_cls – (Optional) The python class for the pitch scale that is used to generate a pitch scale object in the pitch scale method. Defaults to EDOPitchScale

  • ref_frequency – (Optional) A reference frequency on which this tuning is built. For EDOTunings this is the lowest pitch (pitch index 0). Defaults to the frequency for C0 in EDO tunings for A4 = 440Hz (about 16.35 Hz)

property best_fifth

Returns the pitch that best approximates the pure fifth (frequency ratio 3/2) in this tuning.

property fifth

Returns the pitch that represents the fifth of this tuning. In the default implementation, this is the best fifth, however, subclasses can also overwrite this behavior, so e.g. the second-best fifth is returned.

get_ring_number(pitch: EDOPitch | None = None) int

Returns the greatest common divisor of a pitch and the period length of the tuning.

Parameters:

pitch – A pitch of this tuning. (Optional, defaults to the pitch that best approximates the perfect fifth)

property name: str

The name of this tuning

property sharpness: int

Sharpness is an indicator of the pitch difference in EDO tunings between a natural and their sharp version (for example the steps needed to reach C# from C)

The sharpness of an EDO is defined by 7 times the pitch difference between the base pitch and the perfect fifth approximation minus 4 times the pitch difference in an octave.

class xenharmlib.core.tunings.EDTuning(divisions, eq_ratio: ~xenharmlib.core.frequencies.FrequencyRatio, pitch_cls: type[~xenharmlib.core.pitch.EDPitch] = <class 'xenharmlib.core.pitch.EDPitch'>, pitch_interval_cls: type[~xenharmlib.core.pitch.EDPitchInterval] = <class 'xenharmlib.core.pitch.EDPitchInterval'>, pitch_scale_cls: type[~xenharmlib.core.pitch_scale.EDPitchScale] = <class 'xenharmlib.core.pitch_scale.EDPitchScale'>, pitch_interval_seq_cls: type[~xenharmlib.core.pitch_interval_seq.EDPitchIntervalSeq] = <class 'xenharmlib.core.pitch_interval_seq.EDPitchIntervalSeq'>, ref_frequency: ~xenharmlib.core.frequencies.Frequency = Frequency(<Mock name='mock.Rational()' id='139200634434576'>))

EDTuning (“equal division tuning”) takes a base interval given as a frequency ratio and divides this base interval into pitches equally spaced from one another.

For example, the Bohlen-Pierce tuning can be created like this:

>>> from xenharmlib import EDTuning
>>> from xenharmlib import FrequencyRatio
>>> BP = EDTuning(
...     divisions=13,
...     eq_ratio=FrequencyRatio(3)
... )
Parameters:
  • divisions – The number of divisions of the base interval

  • eq_ratio – The frequency factor defining the base interval (e.g. 2 for an octave, 3/2 for a fifth)

  • pitch_cls – (Optional) The python class for the pitch that is used to generate a pitch object in the pitch method. (Not to be confused with the ‘pitch class’ of pitches in periodic tunings). Defaults to EDPitch

  • pitch_interval_cls – (Optional) The python class for the pitch interval that is used to generate a pitch interval object in the pitch interval method. Defaults to EDPitchInterval

  • pitch_scale_cls – (Optional) The python class for the pitch scale that is used to generate a pitch scale object in the pitch scale method. Defaults to EDPitchScale

  • ref_frequency – (Optional) A reference frequency on which this tuning is built. For EDTunings this is the lowest pitch (pitch index 0). Defaults to the frequency for C0 in EDO tunings for A4 = 440Hz (about 16.35 Hz)

get_frequency(pitch: EDPitch) Frequency

Returns the frequency of a given note

Parameters:

note – A note from this tuning

Raises:

IncompatibleOriginContexts – If note is from a different tuning

get_frequency_for_index(pitch_index: int) Frequency

Returns the frequency for a given pitch index

Parameters:

pitch_index – A pitch index

property name: str

The name of this tuning

class xenharmlib.core.tunings.PeriodicTuning(period_length: int, eq_ratio: FrequencyRatio, pitch_cls: type[PeriodicPitchT], pitch_interval_cls: type[PeriodicIntervalT], pitch_scale_cls: type[PeriodicScaleT], pitch_interval_seq_cls: type[PeriodicIntervalSeqT], ref_frequency: Frequency)

This abstract class makes the assumption that the tuning has a period (a fixed distance between two pitches that declares the two pitches as ‘equivalent’). This can be the octave in EDO tunings or a tritave in ED3 tunings.

Periodic tunings implement the len() function that returns the period length:

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> len(edo12)
12

The constructor arguments are:

Parameters:
  • period_length – The number of pitches that constitute a period (for example 12 in 12EDO)

  • eq_ratio – A frequency ratio that defines the equivalency interval

  • pitch_cls – The python class for the pitch that is used to generate a pitch object in the pitch method. (Not to be confused with the ‘pitch class’ of pitches in periodic tunings)

  • pitch_interval_cls – The python class for the pitch interval that is used to generate a pitch interval object in the pitch interval method.

  • pitch_scale_cls – The python class for the pitch scale that is used to generate a pitch scale object in the pitch scale method.

  • ref_frequency – A reference frequency on which this tuning is build.

property eq_ratio: FrequencyRatio

The frequency ratio defining the equivalency interval

property generator_pitches: List[PeriodicPitchT]

Returns a list of pitch objects that can be used to generate the complete set of pitches in this tuning by subsequent interval additions with themselves.

A typical generator pitch in 12-EDO for example is the pitch with index 7 which generates the circle of fifths.

get_ring_number(pitch: PeriodicPitchT) int

Returns the greatest common divisor of a pitch and the period length of the tuning.

Parameters:

pitch – A pitch of this tuning.

pc_scale(pc_indices: List[int] | None = None, root_bi_index: int = 0) ScaleT

Constructs a pitch scale from a list of pitch class indices. The pitch class indices are assumed to be in the order they appear in the scale meaning that e.g. in 12-EDO the provided argument [7, 3, 4] will result in a scale with pitch indices [7, 15, 16]. The base interval of the first provided pc index will always assumed to be 0.

Raises:

InvalidPitchClassIndex – If one of the indices in the list is not a valid pitch class index in this tuning

Parameters:
  • pc_indices – A list of pitch class indices.

  • root_bi_index – Base interval index of the root (optional, defaults to 0)

class xenharmlib.core.tunings.TuningABC(pitch_cls: type[PitchT], pitch_interval_cls: type[IntervalT], pitch_scale_cls: type[ScaleT], pitch_interval_seq_cls: type[IntervalSeqT], ref_frequency: Frequency)

The most abstract tuning class and the base class for all other tunings. AbstractTuning makes next to no assumptions about the tuning, only that it has a reference frequency to ‘center’ the tuning and python classes that define the type of pitch, pitch interval, and pitch scale adjacent to this tuning.

A simple tuning can be derived from this simply by overwriting the method get_frequency() and setting appropriate constructor arguments.

The constructor arguments are:

Parameters:
  • pitch_cls – The python class for the pitch that is used to generate a pitch object in the pitch() method. (Not to be confused with the ‘pitch class’ of pitches in periodic tunings)

  • pitch_interval_cls – The python class for the pitch interval that is used to generate a pitch interval object in the pitch_interval() method.

  • pitch_scale_cls – The python class for the pitch scale that is used to generate a pitch scale object in the pitch_scale() method.

  • ref_frequency – A reference frequency on which this tuning is built.

get_approx_pitch(frequency: Frequency) PitchT

Returns the closest pitch in the tuning to a given frequency.

Parameters:

frequency – The frequency in Hz

abstractmethod get_frequency(pitch: PitchT) Frequency

(Must be overwritten by subclasses) Returns the frequency for a given pitch

abstractmethod get_frequency_for_index(pitch_index: int) Frequency

(Must be overwritten by subclasses) Returns the frequency for a given pitch index

index_scale(pitch_indices: List[int] | None = None) ScaleT

Constructs a pitch scale from a list of pitch indices. According to the definition of a scale indices occuring multiple times will only be considered once. The list of indices will also be sorted automatically.

Parameters:

pitch_indices – A list of pitch indices

pitch(pitch_index: int) PitchT

Returns a pitch having the pitch type this tuning was configured with

Parameters:

pitch_index – An integer denoting the number of steps from the zero pitch.

pitch_interval(pitch_a: PitchT, pitch_b: PitchT) IntervalT

Deprecated since version 0.2.0: Use interval() instead.

Returns a pitch interval having the pitch intervals type this tuning was configured with

Parameters:
  • pitch_a – The starting pitch

  • pitch_b – The target pitch

pitch_range(start, stop=None, step=1)

Returns a generator for continuous pitches of this tuning similar to pythons range function. The method can be called in the familiar ways:

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> for pitch in edo12.pitch_range(3):
...    print(pitch)
EDOPitch(0, 12-EDO)
EDOPitch(1, 12-EDO)
EDOPitch(2, 12-EDO)
>>> for pitch in edo12.pitch_range(5, 10):
...    print(pitch)
EDOPitch(5, 12-EDO)
EDOPitch(6, 12-EDO)
EDOPitch(7, 12-EDO)
EDOPitch(8, 12-EDO)
EDOPitch(9, 12-EDO)
>>> for pitch in edo12.pitch_range(5, 10, 2):
...    print(pitch)
EDOPitch(5, 12-EDO)
EDOPitch(7, 12-EDO)
EDOPitch(9, 12-EDO)
pitch_scale(pitches: List[PitchT] | None = None) ScaleT

Deprecated since version 0.2.0: Use scale() instead.

Returns a pitch scale having the pitch scale type this tuning was configured with

Parameters:

pitches – A list of pitches

property zero_element: PitchT

The zero element is a reference point, in one-dimensional tunings it is the element with index 0, in western notation typically C-0, etc

Pitch and PitchInterval

class xenharmlib.core.pitch.EDOPitch(tuning, frequency, pitch_index: int)

The pitch type for ‘equal division of the octave’ tunings

Parameters:
  • tuning – The tuning to which this pitch belongs

  • frequency – The frequency this pitch represents

  • pitch_index – An integer denoting the pitch (with 0 being the first pitch, 1 being the second, etc)

class xenharmlib.core.pitch.EDOPitchInterval(tuning, frequency_ratio: FrequencyRatio, pitch_diff: int, ref_pitch: PitchT)

Pitch intervals class for ‘equal division of the octave’ pitches

class xenharmlib.core.pitch.EDPitch(tuning, frequency, pitch_index: int)

The pitch type for equal division tunings

Parameters:
  • tuning – The tuning to which this pitch belongs

  • frequency – The frequency this pitch represents

  • pitch_index – An integer denoting the pitch (with 0 being the first pitch, 1 being the second, etc)

class xenharmlib.core.pitch.EDPitchInterval(tuning, frequency_ratio: FrequencyRatio, pitch_diff: int, ref_pitch: PitchT)

Pitch interval class for equal division tunings

class xenharmlib.core.pitch.PeriodicPitch(tuning, frequency, pitch_index: int)

The pitch type for periodic tunings. Depending on the period length it will classify the pitch into a ‘pitch class index’ (pc_index attribute) and a ‘base interval index’ (bi_index)

Parameters:
  • tuning – The tuning to which this pitch belongs

  • frequency – The frequency this pitch represents

  • pitch_index – An integer denoting the pitch (with 0 being the first pitch, 1 being the second, etc)

property bi_index

The base interval index of this pitch

get_generator_index(generator_pitch: Self)

Calculates the number of steps needed to reach this pitch when iteratively adding the given generator to the zero pitch of this tuning

Parameters:

generator_pitch – A generator pitch. Will be normalized to the equivalent pitch in the first base interval if its pitch index exceeds the period length of the tuning.

Raises:
is_equivalent(other: PeriodicPitchLike) bool

Returns True if this pitch has the same frequency as the other object when normalized to the first base interval

Parameters:

other – Another periodic pitch or note

property pc_index

The pitch class index of this pitch

pcs_normalized() Self

Returns the equivalent of this pitch in the first base interval

property pitch_index: int

The index of this pitch as an integer

transpose_bi_index(bi_diff: int) Self

Returns a pitch with the same pitch class index but a transposed base interval

Parameters:

bi_diff – The difference in base interval between this pitch and the resulting one

class xenharmlib.core.pitch.PeriodicPitchInterval(tuning, frequency_ratio: FrequencyRatio, pitch_diff: int, ref_pitch: PitchT)

The pitch interval class for periodic tunings.

get_generator_distance(generator_pitch: PeriodicPitchT) int

Calculates the minimum number of steps needed to reach one pitch from the other when iteratively adding a generator pitch.

A typical application in 12EDO is to calculate the minimum distance of the two pitches on the circle of fifths, hence the generator distance can be a good measure for consonance of an interval given the right generator pitch.

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> M3 = edo12.pitch(0).interval(edo12.pitch(4))
>>> M3.get_generator_distance(edo12.pitch(7))
4
Parameters:

generator_pitch – A generator pitch. Will be normalized to the equivalent pitch in the first base interval if its pitch index exceeds the period length of the tuning.

Raises:

InvalidGenerator – If the pitch is not a generator in the tuning attached to the interval

class xenharmlib.core.pitch.Pitch(tuning, frequency, pitch_index: int)

In its most basic form, a Pitch is a tuple of a pitch index (an integer value) and a tuning that interprets this index as a frequency.

Pitch creates a total ordering on all pitches according to their frequency. This means you can sort pitches in lists (e.g. from lowest frequency to highest frequency). You can also compare pitches, even across different tunings:

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> edo31 = EDOTuning(31)
>>> edo31.pitch(1) < edo12.pitch(1)
True
>>> edo31.pitch(31) == edo12.pitch(12)
True
Parameters:
  • tuning – The tuning to which this pitch belongs

  • frequency – The frequency this pitch represents

  • pitch_index – An integer denoting the pitch (with 0 being the first pitch, 1 being the second, etc)

retune(tuning) Pitch

Approximates this pitch in a different tuning

property short_repr: str

(Must be implemented by subclasses) A shortened representation of this note (to be used in collection objects like scales)

transpose(diff: int | PitchInterval) Pitch

Transposes the pitch to a different one

Parameters:

diff – The difference from this pitch. Can be either an integer (positive for upward movement, negative for downward movement) or a pitch interval

property tuning

The origin tuning of this pitch

class xenharmlib.core.pitch.PitchInterval(tuning, frequency_ratio: FrequencyRatio, pitch_diff: int, ref_pitch: PitchT)

The most abstract form of an interval of two pitches. Implements conversion functions to frequency ratios and a total ordering based on the calculated ratios:

>>> from xenharmlib import EDOTuning
>>> edo31 = EDOTuning(31)
>>> pitch_a = edo31.pitch(4)
>>> pitch_b = edo31.pitch(8)
>>> pitch_c = edo31.pitch(10)
>>> i_ab = pitch_a.interval(pitch_b)
>>> i_ac = pitch_a.interval(pitch_c)
>>> i_ab < i_ac
True

A caveat: Intervals are considered directional in xenharmlib so the order of pitches from which the interval is created is important

Parameters:
  • tuning – The tuning associated with this interval

  • frequency_ratio – The frequency ratio of this interval

  • pitch_diff – An integer that defines the number of steps this interval encompasses (a positive integer means ‘upward steps’, while a negative one means ‘downward steps’)

  • ref_pitch – A reference pitch for the pitch difference. This is necessary for tunings that are not equal step. In just intonation tunings frequency ratios may vary depending on the original pitches used to construct the interval, even if their pitch index difference is the same

classmethod from_pitches(pitch_a: PitchT, pitch_b: PitchT) Self

Deprecated since version 0.2.0: Use from_source_and_target() instead.

Constructs an interval out of two pitches of the same tuning. If the second pitch is lower than the first pitch the Interval will have a negative pitch difference

Raises:

IncompatibleOriginContexts – If pitches come from different tuning systems

Parameters:
  • pitch_a – The first (or reference) pitch

  • pitch_b – The second (or target) pitch

classmethod from_source_and_target(source: PitchT, target: PitchT) Self

Constructs an interval out of two pitches of the same tuning. If the second pitch is lower than the first pitch the Interval will have a negative pitch difference

Raises:

IncompatibleOriginContexts – If pitches come from different tuning systems

Parameters:
  • source – The starting point of the interval

  • target – The end point of the interval

property short_repr: str

A short string representation of the interval (must be implemented by subclass)

PitchScale

A pitch scale is an ordered set of unique pitches in a given tuning. The uniqueness property means that there are no duplicate pitches. However other than in the popular use of the word ‘scale’ the pitch scale object in xenharmlib is not limited to one base interval in periodic tunings. (e.g. C-0 and C-1 are considered distinct) This has a couple of advantages, e.g. that the scale object can be used more generally.

Pitch scales have both a list and a set quality to them. Similar to lists they have an item order, support iteration, positional item retrieval, and slicing. At the same time scales support set operations like intersection, union, symmetric difference, etc.

class xenharmlib.core.pitch_scale.EDOPitchScale(tuning, pitches: List[PitchT] | None = None)

Pitch scale class for ‘equal division of the octave’ tunings

class xenharmlib.core.pitch_scale.EDPitchScale(tuning, pitches: List[PitchT] | None = None)

Pitch scale class for equal division tunings

class xenharmlib.core.pitch_scale.PeriodicPitchScale(tuning, pitches: List[PitchT] | None = None)

Pitch scale class for periodic tunings. Implements operations like rotation and customized set operations (for when you want to treat equivalent pitches the same as equal pitches). It also implements normalization methods.

property pc_indices: List[int]

Returns a list of pitch class indices in the order they appear in this scale. This can include duplicate items if the list has two pitches of the same pitch class

pcs_complement() Self

Normalizes this scale to the first base interval and returns the complement (that is: a scale of all pitches NOT in this scale) as a normalized scale

class xenharmlib.core.pitch_scale.PitchScale(tuning, pitches: List[PitchT] | None = None)

The base class of all pitch scales. Implements list and set operations, transposition, retuning, etc.

PitchScale (or, respectively, its subclasses) are built by the tunings pitch_scale builder method:

>>> from xenharmlib import EDOTuning
>>> edo31 = EDOTuning(31)
>>> scale = edo31.scale(
...     [edo31.pitch(4), edo31.pitch(6), edo31.pitch(9)]
... )

Every pitch will be automatically sorted in its place. The order of the scale is ascending (First lower pitch, then higher pitch)

PitchScale objects support most of the typical list operations:

>>> for pitch in scale:
...     print(pitch)
EDOPitch(4, 31-EDO)
EDOPitch(6, 31-EDO)
EDOPitch(9, 31-EDO)
>>> scale[1]
EDOPitch(6, 31-EDO)
>>> scale[1:-1]
EDOPitchScale([6], 31-EDO)

The ‘in’ operator accepts both pitches and pitch intervals

>>> p = edo31.pitch(4)
>>> p in scale
True
>>> p.interval(edo31.pitch(2)) in scale
True

In regards to intervals, it even works across tunings

>>> edo12 = EDOTuning(12)
>>> edo24 = EDOTuning(24)
>>> edo12_fifth = edo12.pitch(0).interval(edo12.pitch(7))
>>> edo24_scale = edo24.scale(edo24.pitch_range(24))
>>> edo12_fifth in edo24_scale
True

In addition similar operations to the native python sets are available (with slightly different naming and additional method arguments):

  • union

  • intersection

  • difference

  • symmetric_difference

  • is_disjoint

  • is_subset

  • is_superset

add_pitch(pitch: PitchT)

Deprecated since version 0.2.0: objects in xenharmlib are supposed to be immutable

Inserts a new pitch into the scale at the right position

Raises:

IncompatibleOriginContexts – If the pitch has a different tuning than this scale.

Parameters:

pitch – The new pitch

add_pitch_index(pitch_index: int)

Deprecated since version 0.2.0: objects in xenharmlib are supposed to be immutable

Inserts a new pitch into the scale denoted by its pitch index

Parameters:

pitch_index – Index of the pitch

classmethod from_pitch_indices(pitch_indices: List[int], tuning) Self

Creates a scale from a list of pitch indices

Parameters:
  • pitch_indices – A list of pitch indices in any order.

  • tuning – The tuning through which these indices should be interpreted

property is_zero_normalized: bool

Returns True if this function is zero normalized, meaning that the first element of the scale is identical to the pitch with index 0

property pitch_indices: List[int]

A list of the ordered pitch indices present in this scale

retune(tuning) PitchScale

Returns a scale retuned into a different tuning by approximating every pitch in the scale with a pitch from the target tuning.

A caveat: Since pitch scales are a structure of sorted unique pitches this method may produce a scale with a smaller size than the original because two pitches in this tuning can be approximated to the same pitch in the target tuning.

Parameters:

tuning – The target tuning

to_pitch_intervals() List[Interval[PitchT]]

Deprecated since version 0.2.0: Use to_intervals() instead.

Returns this scale represented as a list of pitch intervals

transpose(diff: int | PitchInterval[PitchT]) Self

Transposes the scale upwards or downwards

Parameters:

diff – The difference from this pitch. Can be either an integer (positive for upward movement, negative for downward movement) or a pitch interval

Notation

The notation core module includes primitives to build notation systems. A notation in xenharmlib is defined as a wrapper around a specific tuning that provides a human-friendly string interface to all the lower-level objects (pitch, pitch interval, pitch scale)

exception xenharmlib.core.notation.IncompleteNotation

Gets raised when a notation is not initialized correctly

class xenharmlib.core.notation.NatAccNotation(tuning, note_cls: type[~xenharmlib.core.notes.NatAccNote] = <class 'xenharmlib.core.notes.NatAccNote'>, note_interval_cls: type[~xenharmlib.core.notes.NatAccNoteInterval] = <class 'xenharmlib.core.notes.NatAccNoteInterval'>, note_scale_cls: type[~xenharmlib.core.note_scale.NatAccNoteScale] = <class 'xenharmlib.core.note_scale.NatAccNoteScale'>, note_interval_seq_cls: type[~xenharmlib.core.note_interval_seq.NatAccNoteIntervalSeq] = <class 'xenharmlib.core.note_interval_seq.NatAccNoteIntervalSeq'>)

NatAccNotation is a notation for periodic tunings that select a subset of pitches called naturals to form a basic symbol set (typically letters) and adds special symbols called accidentals, which signify step deviations from the natural pitch classes.

The standard Western notation for example is a such a notation, defining 7 naturals (C, D, E, G, A, B) and 2 accidentals (#, b) that signify a step deviation of +1 and -1 respectively.

The class supports different ‘categories’ of accidentals that do not interact with one another, for example, a category for sharps/flats and one category for ups/downs. Consequently, accidental values are given in the form of a vector.

It assumes that intervals are uniquely defined by their difference in natural index + the difference of the accidental vectors of their source notes. It further assumes that intervals are notated as a tuple (symbol, number). The class implements the 1-based ordinal notation for numbers by default (e.g. the number 1 for a unison, the number 2 for a second, etc), however this behavior get be changed by subclassing and overwriting the method nat_diff_to_interval_number() and its counterpart interval_number_to_nat_diff()

Parameters:
  • tuning – The tuning this notation refers to

  • note_cls – Note class used in the note() builder method (optional, defaults to the class NatAccNote)

  • note_interval_cls – Note interval class used in the note_interval() builder method (optional, defaults to the class NatAccNoteInterval)

  • note_scale_cls – Note scale class used in the note_scale() builder method (optional, defaults to the class NatAccNoteScale)

property acc_symbol_code: SymbolCode

The symbol code for the accidentals. Must be set by the subclass constructor

append_natural(natc_symbol: str, natc_pitch_index: int)

Appends a new natural to this notation. The order in which naturals are added determines their natural class index, so the first added natural will get natural class index 0, the second 1, and so forth.

Raises:

AmbiguousSymbol – If the given natural symbol already denotes a previously appended natural index

Parameters:
  • natc_symbol – A string denoting the natural (typically a single letter)

  • natc_pitch_index – The pitch index of the natural class that is added. For most tunings, this pitch index is equal to the pitch class index because for most tunings there exists no note tuple (natc_symbol, 0) that is not in the first base interval. However, there are outliers like 5-EDO in which (B, 0) = (C, 1) and (B, 0) has a pitch index in the second base interval

balance_interval_acc(nat_diff: int, unbalanced_nat_pitch_diff: int, unbalanced_acc_vector: Tuple[int])

Returns a modified accidental vector that balances the deviation of a pitch diff from the natural pitch diff as defined in this notation. By default, deviations get balanced by adding / subtracting the deviation from the first dimension of the accidental vector.

Parameters:
  • nat_diff – a natural index difference that determines the desired pitch difference in accordance with the mapping of natural differences to pitch differences in this notation

  • unbalanced_nat_pitch_diff – A pitch difference for the natural index that (possibly) deviates from the pitch difference as defined for nat_diff in this notation

  • unbalanced_acc_vector – An accidental vector that is (possibly) unbalanced because the given pitch difference of the natural difference does not match the pitch difference as defined in this notation

balance_note_acc_vector(nat_index: int, unbalanced_nat_pitch_index: int, unbalanced_acc_vector: Tuple[int])

Returns a modified accidental vector that balances the deviation of a pitch index from the natural pitch index as defined in this notation. By default, deviations get balanced by adding / subtracting the deviation from the first dimension of the accidental vector.

Parameters:
  • nat_index – a natural index that determines the desired pitch index in accordance with the mapping of natural indices to pitch indices in this notation

  • unbalanced_nat_pitch_index – A pitch index for the natural index that (possibly) deviates from the pitch index as defined for nat_index in this notation

  • unbalanced_acc_vector – An accidental vector that is (possibly) unbalanced because the given pitch index of the natural index does not match the pitch index as defined in this notation

gen_pc_symbol(natc_index: int, acc_vector: Tuple[int, ...]) Tuple[str, str, str]

Creates a pitch class symbol from a natural class index and an accidental vector. This defaults to calculating the first natural symbol found for natc_index and concatenating it with the minimal accidental symbol configuration for the vector.

The method will return a tuple of 3 with the following semantics:
  • The first element will be the pitch class symbol

  • The second element will be the natural class symbol

  • The third element will be the accidental symbol string

(Subclasses can overwrite this method if they e.g wish to generate pc_symbols that have post-fix or in-fix naturals)

Parameters:
  • natc_index – A natural class index of a note

  • acc_vector – An accidental value vector

get_acc_symbol(acc_vector: Tuple[int, ...]) str

Returns a symbol string for an accidental vector, like (1, 0) -> ‘#’ or (-1, 1) -> ‘^b’

Raises:

InvalidAccidentalValue – If the accidental symbol code of this notation does not have a symbol or symbol combination that maps to this value

Parameters:

acc_vector – An integer vector denoting the step deviation from the natural pitch class

get_interval_symbol(nat_diff: int, acc_vector: Tuple[int]) str

Returns the interval symbol for a natural/accidental note interval. Interval symbols depend on the natural index difference class of the two notes (e.g. if the interval is a unison, a third, a fifth, etc) and the deviation from the standard pitch difference of a natural difference (In 12-EDO this standard pitch difference would e.g. be 7 for a fifth, 4 for a third, etc)

Raises:

IncompleteNotation – If no symbol code was registered for the given parameters

Parameters:
  • nat_diff – The difference in natural indices

  • acc_vector – The accidental vector of the interval

get_natc_symbol(nat_index: int) str

Returns a string symbol for a natural index like 0 -> ‘C’ or 8 -> ‘D’ in 12-EDO

Raises:

InvalidNaturalIndex – If the natural index is smaller than 0

Parameters:

nat_index – A natural index of this notation

interval_number_to_nat_diff(interval_number: int) int

Returns a natural index difference for an interval number. By default, it assumes that the interval number is given in 1-based ordinal notation. Subclasses can change this behavior by overwriting this method.

Parameters:

interval_number – An interval number

is_natural(pitch_index: int) bool

Returns True if the given pitch index refers to a natural in this notation, False otherwise

Parameters:

pitch_index – The pitch index to consider

property nat_count: int

Returns the number of registered natural symbols for this notation (typically 7 for Western-style notations)

nat_diff_to_interval_number(nat_diff: int) int

Returns an interval number for a natural index difference. By default, it returns a 1-based ordinal number. Subclasses can change this behavior by overwriting this method.

Parameters:

nat_diff – The natural index difference that characterizes the interval

nat_index_to_pc_index(nat_index: int) int

Returns the pitch class index a natural index refers to

Parameters:

nat_index – A natural index

nat_index_to_pitch_index(nat_index: int) int

Returns the pitch index a natural index refers to (e.g. in 12-EDO: 0 -> 0, 1 -> 2, 3 -> 4, 4 -> 5)

Parameters:

nat_index – A natural index

property natc_pc_indices: List[int]

A sorted list of natural class pitch class indices that are present in this notation

property natc_pitch_indices: List[int]

A sorted list of natural class pitch indices that are present in this notation

natural_scale(bi_index: int = 0) NatAccNoteScale

Creates a scale with all the naturals in this notation in a specific base interval (in Western notations this is typically the C major scale)

Parameters:

bi_index – (optional, defaults to 0). The index of the base interval the notes should reside in

note(pc_symbol: str, nat_bi_index: int) NatAccNote

Creates a note in line with this notation

Parameters:
  • pc_symbol – A symbol denoting the pitch class (typically something like ‘C#’, ‘Ab’, ‘F’, etc)

  • nat_bi_index – The base interval index of the natural (for example a B#-0 in 12-EDO has the natural base interval index of 0, even though the pitch is in base interval 1)

note_by_numdef(nat_index: int, acc_vector: Tuple[int, ...]) NatAccNote

Creates a natural/accidental note by its numerical definition. Autogenerates appropriate symbols

Parameters:
  • nat_index – The natural index of the note

  • acc_vector – The accidental vector of the note

note_interval(note_a: NatAccNote, note_b: NatAccNote) NatAccNoteInterval

Deprecated since version 0.2.0: Use interval() instead.

Creates a note interval between two notes created by this notation

Raises:

IncompatibleOriginContexts – If one of the notes has a different notation than this one

Parameters:
  • note_a – The source note

  • note_b – The target note

note_scale(notes: List[NatAccNote] | None = None) NatAccNoteScale

Deprecated since version 0.2.0: Use scale() instead.

Creates a note scale from a list of notes

Raises:

IncompatibleOriginContexts – If one of the notes has a different notation than this one

Parameters:

notes – A list of notes created by this notation

parse_pc_symbol(pc_symbol: str) Tuple[str, str, int, Tuple[int, ...]]

Parses a pitch class symbol into its natural class symbol part and its accidental symbol part. Returns a 4-tuple (natc_symbol, acc_symbol, natc_index, acc_vector) with the parsing result.

pc_scale(pc_symbols: List[str] | None = None, root_nat_bi_index: int = 0) NatAccNoteScale

Constructs a note scale from a list of pitch class symbols. The pitch class symbols are assumed to be in the order they appear in the scale meaning that e.g. in 12-EDO the provided argument [‘G’, ‘D’, ‘E’] will result in a scale with notes G0, D1, E1. The base interval of the natural of the first provided pc symbol will always assumed to be 0.

Raises:

UnknownNoteSymbol – If one of the pc symbols is not valid in the definition of this notation

Parameters:
  • pc_symbols – A list of pitch class symbols.

  • root_nat_bi_index – (optional, defaults to 0) The base interval index of the natural of the root (for example a B#-2 in 12-EDO has the natural base interval index of 2, even though the pitch is in base interval 3).

set_interval_symbol_code(nat_diffc: int, symbol_code: SymbolCode)

Sets an interval class symbol for a natural index difference class. The natural index difference class is a number between 0 and the number of naturals in the notation (exclusive), so e.g. [0, …, 6] in a traditional Western system that has 7 naturals. It is calculated by taking the absolute distance of two natural indices modulo the number of naturals in the notation, so e.g. 2 for intervals (C0, E#0), (C0, E1) and (E#2, C0).

The natural index difference class is closely related to the Roman numeral index of intervals, for example, a difference of 2 is the same as III, a difference of 0 is the same as I, etc.

Associating a natural index difference class with a specific symbol code allows setting different interval naming schemes for different interval numbers, e.g. making a difference between perfect and imperfect interval naming schemes. In the Western system differences 0 (unison), 3 (fourth) and 4 (fifth) use the P/A/d interval symbols while for differences 1 (second), 2 (third), 5 (sixth), 6 (sevenths) the system M/m/A/d is used.

Raises:

InvalidNaturalDiffClassIndex – If the natural diff class index is out of bounds

Parameters:
  • nat_diffc – The difference of the natural indices forming the interval modulo the naturals count

  • symbol_code – A symbol code defining how the center and the deviations from it should be represented as strings.

shorthand_interval(symbol: str, number: int) NatAccNoteInterval

Creates an interval without specifying two notes.

A caveat for tunings that are not equal-step: Intervals can have irregular sizes, even if they are notated the same. This method will automatically add some reference note to the interval to be able to calculate ANY size of the interval, so the result of this method might differ in size from a result that you obtained by forming an interval through the note_interval method.

Parameters:
  • symbol – An interval symbol of this notation (for example P, A, M, m)

  • number – An interval number indicating the interval step width according to the convention laid out by this notation

std_pitch_diff(nat_diff: int) int

Returns the standardized pitch difference for a natural index difference (e.g. in 12-EDO: 0 -> 0, 1 -> 2, 4 -> 7, (-1) -> (-2), (-4) -> (-7), etc)

Parameters:

nat_diff – A natural index difference

property zero_element: NatAccNote

The ‘standard note’ with pitch_index 0

class xenharmlib.core.notation.NotationABC(tuning, note_cls: type[NoteT], note_interval_cls: type[IntervalT], note_scale_cls: type[ScaleT], note_interval_seq_cls: type[IntervalSeqT])

Abstract base class for all notations. A notation can be understood as a wrapper around the tuning, providing a string interface to the underlying integer system.

Notations in the core package are defined as generics with three type variables: One for the note class, one for the interval class, and one for the scale class.

Parameters:
  • tuning – The tuning for which the notation should be constructed

  • note_cls – The python class that is used to generate the note object in the note method.

  • note_interval_cls – The python class that is used to generate a note interval object in the note_interval method.

  • note_scale_cls – The python class that is used to generate a note scale object in the note_scale method.

property enharm_strategy

The enharmonic strategy of this notation. Enharmonic strategies define different ways to map pitch layer objects to notation layer objects.

guess_note(pitch) NoteT

Guesses a note from a pitch using the preferred enharmonic strategy of this notation

Pitch:

A pitch object originating from the underlying tuning

guess_note_interval(pitch_interval) NoteT

Guesses a note interval from a pitch interval using the preferred enharmonic strategy of this notation

Pitch_interval:

A pitch interval object originating from the underlying tuning

guess_note_scale(pitch_scale) NoteT

Guesses a note scale from a pitch scale using the preferred enharmonic strategy of this notation

Pitch_scale:

A pitch scale object originating from the underlying tuning

abstractmethod note(*args, **kwargs) NoteT

(Must be overwritten by subclasses) Returns a note object of the note type this notation was initialized with

abstractmethod note_interval(note_a: NoteT, note_b: NoteT) IntervalT

Returns a note interval of the note interval type this notation was initialized with

Parameters:
  • note_a – The source note

  • note_b – The target note

abstractmethod note_scale(notes: List[NoteT] | None = None) ScaleT

Returns a note scale of the note scale type this notation was initialized with

Parameters:

notes – A list of notes

property tuning

Returns the tuning this notation was built for

Note and NoteInterval

The note core module implements primitives to handle different types of notes and note intervals. Notes and note intervals wrap the integer-based pitch and pitch interval classes.

class xenharmlib.core.notes.NatAccNote(notation, frequency, pitch_index, nat_index: int, acc_vector: Tuple[int, ...], pc_symbol: str, natc_symbol: str, acc_symbol: str)

A base class for notes that are constructed from a natural and accidentals (the appropriate base class for notes of notations subclassing from NatAccNotation)

Parameters:
  • notation – The notation object this note belongs to

  • frequency – The frequency this note represents

  • pitch_index – The pitch index of this note

  • nat_index – The natural index of this note, which is an index counting the naturals starting with 0 (e.g. in Western notation C0 ^= 0, D0 ^= 1, C1 ^=7, etc)

  • acc_vector – A vector detailing the different deviations in steps that were introduced through accidentals

  • pc_symbol – The chosen symbol for the pitch class (in most notations this is equal to natc_symbol + acc_symbol, however, there are notations - like UpDownNotation - that put some of the accidentals before the natural)

  • natc_symbol – The chosen symbol for the natural class (e.g. ‘C’ for C#)

  • acc_symbol – The chosen symbol for the accidental (e.g. ‘#’ for C#)

acc_altered(acc_diff: Tuple[int, ...])

Returns a note with altered accidentals from an accidental difference vector, so for example in UpDownNotation for a tuning with sharpness 2 altering ^C# by (2, -1) results in the note Cx

Parameters:

acc_diff – The accidental difference vector

property acc_direction: int

The accidental direction of this note (0 if the note is a natural, 1 if the note is a sharp note, -1 if it is a flat note)

property acc_symbol: str

The symbol for the accidental of this note

property acc_value: int

The accidental value of this note (e.g. in 31edo 2 for #, -2 for b, 0 for natural)

property acc_vector: Tuple[int, ...]

The accidental vector of this note

property is_enharmonic_natural: bool

Returns True if note refers to a pitch class that is a natural

is_notated_equivalent(other) bool

Returns True, if this note is notated the same way as the other, False otherwise

Parameters:

other – Another note to compare

property is_notated_natural: bool

Returns True if this note is notated(!) as a natural, False otherwise (e.g. the note E# refers to a natural, however, it is notated with an accidental, thus the property will be False here)

is_notated_same(other) bool

Returns True, if this note is notated the same way as the other, False otherwise

Parameters:

other – Another note to compare

property nat_bi_index: int

The base interval index of the natural of this note

property nat_index: int

Returns the natural index of this note. The natural index is the number of steps needed to reach the natural part of this note, so for example in a notation with naturals C, D, E, F, G, A, B the natural index of C#-0 is 0, D-1 is 8, Eb-3 is 16

property nat_pc_index: int

The pitch class index of the natural of this note

property nat_pitch_index: int

The pitch index of the natural of this note

property natc_index: int

Returns the natural class index of this note. The natural class index is the equivalency class of the natural index, so for example in a notation with naturals C, D, E, F, G, A, B the notes C#-3 and Cb-0 both have natural class index 0 while F#-2 and Fbb-5 have natural class index 3

property natc_pitch_index: int

The pitch index of the natural class of this note

property natc_symbol: str

The symbol for the natural of this note

property pc_short_repr

The pitch class symbol of this note

property pc_symbol: str

The pitch class symbol of this note

property pitch: PeriodicPitch

Returns the underlying pitch object

property short_repr

A shortened representation of this note

transpose(diff: int | NatAccNoteInterval) NatAccNote

Transposes the note to another one by a natural/accidental note interval.

Parameters:

diff – A natural/accidental note interval object or an integer denoting the pitch difference

transpose_bi_index(bi_diff: int) Self

Returns a note with the same pitch class index and symbol, but with a transposed base interval

Parameters:

bi_diff – The difference in base interval between this note and the resulting one

class xenharmlib.core.notes.NatAccNoteInterval(notation, frequency_ratio, pitch_diff, ref_note: NatAccNote, nat_diff: int, acc_vector: Tuple[int, ...], symbol: str, number: int)

Note interval class for intervals with natural/accidental notes. The class assumes that the interval is value-representable by the difference in natural indices and an accidental vector signifying step alterations of different categories. It is meant as a solid basis for interval notations that are similar to the traditional Western interval notation having a interval symbol (like ‘M’) and an interval number (like 2)

The concrete way an interval symbol and number are chosen is dependent on the underlying notation from which a symbol and a number are received in the from_source_and_target() builder method.

Parameters:
  • notation – The notation this interval refers to

  • frequency_ratio – A frequency ratio object

  • pitch_diff – The difference in pitch that this interval represents

  • ref_note – A reference note (needed for non-equal step tunings)

  • nat_diff – The difference of the natural indices of the two notes defining the interval

  • acc_vector – A vector defining the alteration of the standard pitch index difference of a natural index difference

  • symbol – An interval symbol (like ‘M’, ‘d’, ‘P’)

  • number – An interval number

property acc_vector: Tuple[int, ...]

The accidental vector of this interval (signifying the different pitch deviations from the standard natural pitch difference)

classmethod from_notes(note_a: NatAccNote, note_b: NatAccNote) Self

Deprecated since version 0.2.0: Use from_source_and_target() instead.

Creates a note interval from two notes

Raises:

IncompatibleOriginContexts – If notes belong to different notations

Parameters:
  • note_a – The source note

  • note_b – The target note

classmethod from_source_and_target(source: NatAccNote, target: NatAccNote) Self

Creates a note interval from two notes

Raises:

IncompatibleOriginContexts – If notes belong to different notations

Parameters:
  • source – The source note

  • target – The target note

property nat_diff: int

The difference of the natural indices of the two notes forming the interval

property number: int

A number signifying the size of the interval (closely related to the nat_diff property but traditionally implemented as 1-based index)

property short_repr: str

A short representation string of the interval (to be shown in collections)

property shorthand_name: Tuple[str, int]

A tuple consisting of the interval symbol and the interval number

property symbol: str

A symbol classifying this interval in regard to size and quality

class xenharmlib.core.notes.NoteABC(notation, frequency, pitch_index)

Abstract base class for notes. Implements the properties tuning, frequency and pitch_index as well as the equality and lesser-than relation based on the frequency property.

Subclasses must implement the pitch property, the is_notated_same method and the transpose() method.

Parameters:
  • notation – The notation object this note belongs to

  • pitch_index – The pitch index of this note

  • frequency – The frequency this note represents

property enharm_strategy

Proxy property for the enharmonic strategy of the notation

abstractmethod is_notated_same(other) bool

(Must be implemented by subclasses) Returns True, if this note is notated the same way as the other, False otherwise

Parameters:

other – Another note of the same notation or class

property notation

The notation associated with this note

abstract property pitch

(Must be implemented by subclasses) Returns the underlying pitch object

property tuning

The tuning associated with this note

class xenharmlib.core.notes.NoteIntervalABC(notation, frequency_ratio, pitch_diff: int, ref_note: NoteT)

Abstract base class for note intervals. Implements the property pitch_interval that constructs the equivalent pitch interval

Note intervals are implemented as generic types with the inner type being a note class.

Subclasses must at least implement the from_source_and_target() class method.

Parameters:
  • notation – The notation this interval refers to

  • frequency_ratio – A frequency ratio object

  • pitch_diff – The difference in pitch that this interval represents

  • ref_note – A reference note (needed for non-equal step tunings)

property notation

The notation associated with this note interval

property pitch_interval

Returns the pitch interval equivalent to this note interval

property ref_note: NoteT

A reference note for the interval. (This is important for tunings that are not equal step where the same pitch difference does not imply the same frequency ratio)

property tuning

The tuning associated with this note interval

class xenharmlib.core.notes.PeriodicNoteABC(notation, frequency, pitch_index)

Abstract base class for periodic notes. Implements proxy properties pc_index and bi_index that refer to the underlying periodic pitch object.

Subclasses need to implement the transpose_bi_index() method (in addition to the abstract properties and methods of NoteABC)

property bi_index: int

The base interval index of this note

get_generator_index(generator_note: Self)

Calculates the number of steps needed to reach this note when iteratively adding the pitch of the given generator note to the zero pitch of this tuning

Parameters:

generator_note – A generator note. Will be normalized to the equivalent note in the first base interval if its pitch index exceeds the period length of the tuning.

Raises:
is_equivalent(other: PeriodicPitchLike) bool

Returns True if this note has the same frequency as the other object when normalized to the first base interval

Parameters:

other – Another periodic pitch or note

abstractmethod is_notated_equivalent(other) bool

(Must be implemented by subclasses) Returns True, if this note is notated the same way as the other in regards to its pitch class symbol

Parameters:

other – Another note

property pc_index: int

The pitch class index of this note

pcs_normalized() Self

Returns the equivalent of this note in the first base interval

abstractmethod transpose_bi_index(bi_diff: int) Self

Returns a note with the same pitch class index and symbol, but with a transposed base interval

Parameters:

bi_diff – The difference in base interval between this note and the resulting one

class xenharmlib.core.notes.PeriodicNoteInterval(notation, frequency_ratio, pitch_diff: int, ref_note: NoteT)

Abstract base class for intervals referring to notations of periodic tunings.

Implements the method get_generator_distance()

get_generator_distance(generator_note: NoteT) int

Calculates the minimum number of steps needed to reach one note from the other when iteratively adding a generator note.

A typical application in 12EDO is to calculate the minimum distance of the two notes on the circle of fifths, hence the generator distance can be a good measure for consonance of an interval given the right generator note.

Parameters:

generator_note – A generator note. Will be normalized to the equivalent pitch in the first base interval if its pitch index exceeds the period length of the tuning.

Raises:

InvalidGenerator – If the note is not a generator in the tuning attached to this interval’s notation

NoteScale

The note scale core module implements basic classes for different types of scale notation systems.

class xenharmlib.core.note_scale.NatAccNoteScale(notation, notes=None)

Basic note scale class for natural/accidental notations. Implements the scale equivalents of properties special to natural/accidental notes.

property acc_directions: List[int]

The list of accidental directions of notes in the scale (0 if the note is a natural, 1 if the note is a sharp note, -1 if it is a flat note, so for example in 31-EDO [0, 1, -1] for [C0, ^B#2, Cb0])

property acc_symbols: List[str]

The symbol list for the accidental part of each note in the scale (e.g. in 12-EDO [‘#’, ‘b’, ‘’] for [C#0, Gb1, B4])

property acc_values: List[int]

A list of accidental values for each note in the scale

property acc_vectors: List[int]

A list of accidental vectors for each note in the scale

property nat_bi_indices: List[int]

A list of natural base interval indices represented in this scale. The natural base interval is the base interval index of the natural part of the note, so e.g. 0 for B#-0

property nat_indices: List[int]

A list of the natural indices of notes in this scale

The natural index is the number of natural steps needed to reach the natural part of this note, so for example in a notation with naturals C, D, E, F, G, A, B the natural index of C#-0 is 0, D-1 is 8, Eb-3 is 16

property nat_pc_indices: List[int]

A list of pitch class indices of the natural part of each note in the scale (e.g. in 12-EDO [0, 2, 4] for [C#0, D1, Eb2])

property nat_pitch_indices: List[int]

A list of pitch indices of the natural part of each note in the scale (e.g. in 12-EDO [0, 14, 18] for [C#0, D1, Eb2])

property natc_indices: List[int]

A list of natural class indices of notes in this scale.

The natural class index is the equivalency class of the natural index, so for example in a notation with naturals C, D, E, F, G, A, B the notes C#-3 and Cb-0 both have natural class index 0 while F#-2 and Fbb-5 have natural class index 3

property natc_symbols: List[str]

The symbol list for the natural part of each note in the scale (e.g. in 12-EDO [‘C’, ‘G’, ‘B’] for [C#0, Gb1, B4])

property pc_symbols: List[str]

The symbol list for the pitch classes represented in the scale (e.g. in 12-EDO [‘C#’, ‘Gb’, ‘B’] for [C#0, Gb1, B4])

class xenharmlib.core.note_scale.NoteScale(notation, notes=None)

Base class for all note scales. Implements list and set operations, transposition, etc

Note scales are implemented as generic types with the inner type being a note class.

Parameters:
  • notation – The notation this scale refers to

  • notes – (optional) A list of notes from the notation. If the parameter is omitted an empty scale will be initialized

add_note(note: NoteT)

Deprecated since version 0.2.0: objects in xenharmlib are supposed to be immutable

Inserts a new note into to the scale at the right position. If the note already exists in the scale the method will do nothing.

Raises:

IncompatibleOriginContexts – If the note has a different notation than this scale.

Parameters:

note – The new note

property enharm_strategy

A proxy property to the enharmonic strategy of the notation

is_notated_disjoint(other: Self) bool

Determines if this scale has any common notes with another scale of the same notation. In contrast to is_disjoint enharmonically equivalent but differently notated notes will be treated as distinct

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

is_notated_same(other: Self) bool

Returns True if this scale has the exact same notes as the other scale while ignoring possible enharmonic equivalence.

is_note_subset(other: Self, proper: bool = False) bool

Determines if all notes in this scale also exist in the other scale. In contrast to is_subset enharmonically equivalent but differently notated notes will be treated as distinct

Parameters:
  • other – Another scale of the same notation

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

is_note_superset(other: Self, proper: bool = False) bool

Determines if all notes in the other scale also exist in this scale. In contrast to is_superset enharmonically equivalent but differently notated notes will be treated as distinct

Parameters:
  • other – Another scale of the same notation

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

property is_zero_normalized: bool

Returns True if this function is zero normalized, meaning that the first element of the scale is notated the same as the zero element of the origin context (typically C0 in western-like notations)

note_difference(other: Self) Self

Returns a new scale containing only notes from this scale that are NOT present in the other scale. In contrast to the difference method notes will only be considered shared notes of the sets if they are notated the same. If a note is in the second set that is enharmonically equivalent to a note in this set but notated in a different way, the latter will stay in the result set.

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

note_intersection(other: Self) Self

Returns a new scale including all notes that are included in both scales. In contrast to the intersection method notes will only be considered shared notes of the sets if they are notated the same and excluded otherwise, even if they are enharmonically equivalent

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

property pitch_indices: List[int]

An ordered list of pitch indices present in this scale

property pitch_scale

Returns the equivalent pitch scale for this object

to_note_intervals() List[NoteIntervalABC]

Deprecated since version 0.2.0: Use to_intervals() instead.

Returns this scale represented as a list of note intervals

transpose(diff: int | NoteIntervalABC) Self

Transposes the scale by the given interval

Parameters:

diff – A note interval or pitch difference given as an integer

property tuning

The tuning the origin notation of this scale relies upon

class xenharmlib.core.note_scale.PeriodicNoteScale(notation, notes=None)

Note scale class for periodic notations. Implements customized set operations (for when you want to treat equivalent notes the same as equal notes).

is_notated_disjoint(other: Self, ignore_bi_index: bool = False) bool

Determines if this scale has any common notes with another scale of the same notation. In contrast to is_disjoint enharmonically equivalent but differently notated notes will be treated as distinct

Parameters:
  • other – Another scale of the same notation

  • ignore_bi_index – (Optional, default False) When set to True notes of the same pitch class will be treated the same. For example, if one scale includes C-0 and another C-1 the scales will not be considered disjoint

Raises:

IncompatibleOriginContexts – If the other scale originates from a different notation

is_notated_equivalent(other: Self) bool

Returns True if this scale has, apart from the base interval, the exact same notes as the other while ignoring possible enharmonic equivalence.

is_note_subset(other: Self, proper: bool = False, ignore_bi_index: bool = False) bool

Determines if all notes in this scale also exist in the other scale. In contrast to is_subset enharmonically equivalent but differently notated notes will be treated as distinct

Parameters:
  • other – Another scale of the same notation

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

  • ignore_bi_index – (Optional, default False) When set to True notes of the same pitch class will be treated the same.

Raises:

IncompatibleOriginContexts – If the other scale originates from a different notation

is_note_superset(other: Self, proper: bool = False, ignore_bi_index: bool = False) bool

Determines if all notes in the other scale also exist in this scale. In contrast to is_superset enharmonically equivalent but differently notated notes will be treated as distinct

Parameters:
  • other – Another scale of the same notation

  • proper – (Optional, default False) When set to True method will return False if the two sets are identical

  • ignore_bi_index – (Optional, default False) When set to True notes of the same pitch class will be treated the same.

Raises:

IncompatibleOriginContexts – If the other scale originates from a different notation

note_difference(other: Self, ignore_bi_index: bool = False) Self

Returns a new scale containing only notes from this scale that are NOT present in the other scale. In contrast to the difference method notes will only be considered shared notes of the sets if they are notated the same. If a note is in the second set that is enharmonically equivalent to a note in this set, but notated in a different way, the latter will stay in the result set.

Parameters:
  • other – Another scale of the same notation

  • ignore_bi_index – (Optional, default False) When set to True notes of the same pitch class will be treated the same. For example, if the difference of two scales including C-0 and C-1 respectively is calculated, C-0 will not be inserted into the new scale

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

note_intersection(other: Self, ignore_bi_index: bool = False) Self

Returns a new scale including all notes that are included in both scales. In contrast to the intersection method notes will only be considered shared notes of the sets if they are notated the same and excluded otherwise, even if they are enharmonically equivalent

Parameters:

ignore_bi_index – (Optional, default False) When set to True notes of the same pitch class will be treated the same. For example, if the intersection of two scales including C-0 and C-1 respectively is calculated, both notes will be added to the result

Raises:

IncompatibleOriginContexts – If the other scale has a different notation

property pc_indices: List[int]

Returns a list of pitch class indices in the order they appear in this scale. This can include duplicate items if the scale has two notes of the same pitch class

pcs_complement() Self

Returns a complement version of this scale that includes all the notes in the first base interval that are not part of this scale

Enharmonic Strategies

This module includes functionality to deal with enharmonic ambiguity

class xenharmlib.core.enharm_strategies.EnharmonicStrategy

An enharmonic strategy is a drop-in function set to solve the problem of enharmonic ambiguity when translating pitches into notes.

An example: On the pitch/tuning layer the transpose method is well-defined if given an integer:

>>> from xenharmlib import EDOTuning
>>> edo12 = EDOTuning(12)
>>> edo12.pitch(0).transpose(1)
EDOPitch(1, 12-EDO)

However on the notation layer it is unclear, if “C + 1” should result in C# or Db, if “C + 2” should result in “D” or “C##”, etc. The same problem is encountered on operations like pcs_complement: Should the PCS complement of [C, D, E, F, G, A, B] be notated with upwards accidentals [C#, D#, F#, G#, A#], downward accidentals [Db, Eb, Gb, Ab, Bb] or a mixture of both?

An enharmonic strategy makes an opinionated(!) choice which pitches translate to which notes. Because not every strategy is fit for every context and purpose xenharmlib allows choosing a custom strategy when initializing a notation.

This base class implements stubs of all hook functions which get called by the notation layer classes. By default these stubs are not abstract, but simply raise NotImplementedError, so it is possible for EnharmonicStrategy subclasses to not support all operations that need an enharmonic strategy. This way custom enharmonic strategies implemented by the user also keep working if the feature set expands on an update.

guess_note(notation, pitch)

Notation.guess_note relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch – The pitch object

guess_note_interval(notation, pitch_interval)

Notation.guess_note_interval relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch_interval – The pitch interval object

guess_note_scale(notation, pitch_scale)

Notation.guess_note_scale relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch_scale – The pitch scale object

note_scale_pcs_complement(note_scale)

NoteScale.pcs_complement relays to here

Parameters:

note_scale – The note scale on which the pcs_complement method was called

note_scale_transpose(note_scale, pitch_diff: int)

NoteScale.transpose relays to here if the interval argument was not given as a suitable NoteInterval object but as an integer.

Parameters:
  • note_scale – The note scale on which the transpose method was called

  • pitch_diff – The pitch difference as an integer

note_transpose(note, pitch_diff: int)

Note.transpose relays to here if the interval argument was not given as a suitable NoteInterval object but as an integer.

Parameters:
  • note – The note on which the transpose method was called

  • pitch_diff – The pitch difference as an integer

class xenharmlib.core.enharm_strategies.PCBlueprintStrategy(pc_blueprint: Sequence[PeriodicNoteABC])

PCBlueprintStrategy is an enharmonic strategy that defines fixed note symbols for each pitch class and translates every pitch to a note by matching the pitch class and transposing the base interval.

Parameters:

pc_blueprint – An iterable of notes that together form a pitch class blueprint for the whole pitch range

>>> from xenharmlib import EDOTuning
>>> from xenharmlib import UpDownNotation
>>> from xenharmlib.core.enharm_strategies import PCBlueprintStrategy
>>>
>>> edo12 = EDOTuning(12)
>>> n_edo12 = UpDownNotation(edo12)
>>>
>>> S = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
>>> strategy = PCBlueprintStrategy(
...     [n_edo12.note(symbol, 0) for symbol in S]
... )
>>> n_edo12.enharmonic_strategy = strategy
>>>
>>> n_edo12.guess_note(edo12.pitch(13))
UpDownNote(C#, 1, 12-EDO)
>>> n_edo12.note('D#', 2).transpose(1)
UpDownNote(E, 2, 12-EDO)
guess_note(notation, pitch)

Notation.guess_note relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch – The pitch object

guess_note_interval(notation, pitch_interval)

Notation.guess_note_interval relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch – The pitch interval object

guess_note_scale(notation, pitch_scale)

Notation.guess_note_scale relays to here

Parameters:
  • notation – The notation object that relayed here

  • pitch_scale – The pitch scale object

note_scale_pcs_complement(note_scale)

NoteScale.pcs_complement relays to here

Parameters:

note_scale – The note scale on which the pcs_complement method was called

note_scale_transpose(note_scale, pitch_diff: int)

NoteScale.transpose relays to here if the interval argument was not given as a suitable NoteInterval object but as an integer.

Parameters:
  • note_scale – The note scale on which the transpose method was called

  • pitch_diff – The pitch difference as an integer

note_transpose(note, pitch_diff: int)

Note.transpose relays to here if the interval argument was not given as a suitable NoteInterval object but as an integer.

Parameters:
  • note – The note on which the transpose method was called

  • pitch_diff – The pitch difference as an integer

Symbol Codes

The symbol module implements primitives to parse languages in which each literal and each word represents an integer vector. These languages are called ‘symbol codes’ and are used as utils in notations.

exception xenharmlib.core.symbols.AmbiguousSymbol

Gets raised whenever a symbol is added to a symbol code that already exists or if the associated value is already represented by another symbol

class xenharmlib.core.symbols.SymbolArithmetic(dimensions: int = 1, offset: Tuple[int, ...] | None = None, allow_empty: bool = False)

A symbol arithmetic is a mapping between string symbol sequences and integer vector sums.

A simple use case is to parse and generate accidentals, for example parsing the standard western accidental string ‘x#b’ into a list of one-dimensional integer vectors that signify the pitch index alterations of each accidental (like (2,), (1,), (-1,)), resulting in the sum (2,) denoting the total pitch index alteration of an accidental string.

Higher dimensional arithmetics can be useful if there are multiple classes of accidentals (like sharp/flat on the one hand and up/down on the other). Given a value dimensionality of 2, it can e.g. parse an expression like ‘^b##x’ into a list of integer vectors (here: (0, 1), (-1, 0), (1, 0), (1, 0), (2, 0)) from which it creates a sum vector (3, 1)

Vice-versa for a given integer or integer vector it can create an equivalent minimal sequence of symbols (e.g. (-1, 1) -> ‘b^’).

SymbolArithmetic parses in a greedy way, so if ‘bb’, ‘b’ and ‘#’ are registered as symbols, it will parse ‘bb#’ into the list ‘bb’, ‘#’ (NOT ‘b’, ‘b’, ‘#’)

The class can also be used to design accidental systems for dense tunings (like prime limit tunings), that don’t have an enumerable pitch index sequence. For example, given a 3-limit tuning one can define accidentals as their monzo, defining ‘#’ as the value vector (-11, 7), ‘b’ as the vector (11, -7), and so forth. The addition of the monzo vectors is then equal to the product in |R+: (e.g. ‘b#’ = (11, -7) + (-11, 7) = (0, 0), which is the same as (2^11)/(3^7) * (3^7)/(2^11) = (2^0) * (3^0) = 1.

On initialization of an arithmetic, an offset can be set, which adds a fixed integer vector to all symbol value vectors. This is especially powerful when defining partial arithmetics in a SymbolArithmeticSet, e.g. if one wants to parse ‘^A’ into (4, 1), ‘AA’ into (5, 0), ‘^AAA’ into (6, 1), etc. In a case like this one can define the value of ‘A’ to be (1, 0), the value of ‘^’ to be (0, 1) and the offset to be (3, 0).

Parameters:
  • dimensions – Dimensions of the value vector (optional, defaults to 1)

  • offset – (optional, defaults to the 0-vector). A fixed value vector that will be added to the sum

  • allow_empty – (optional, default False). If True, empty strings are part of this arithmetic (with the value of the offset, or the 0 vector if offset is not given). If False exceptions will be raised on empty strings

add_symbol(symbol: str, vector: Tuple[int, ...], position: int | None = None, min_occurence: int | None = None, max_occurence: int | None = None)

Adds a string symbol with its corresponding integer vector to this arithmetic

Raises:

AmbiguousSymbol – If symbol already exists in the arithmetic or if vector is already represented by another symbol

Parameters:
  • symbol – A string (can be multi-character)

  • vector – An integer tuple defining the value vector of the symbol (dimensions must match the dimensions with which the arithmetic was initialized)

  • position – The desired positional value of the symbol in the sorting process of get_symbol_str (optional, if no parameter is given the position of the symbol will be analogous to the order in which symbols were added to the arithmetic)

  • min_occurence – (optional) The minimum number of times this symbol must occur in the arithmetic symbol string in order for the string to be considered valid

  • max_occurence – (optional) The maximum number of times this symbol can occur in the arithmetic symbol string in order for the string to be considered valid

get_symbol_str(vector: Tuple[int, ...]) str

Partitions the given vector into vector summands that are represented by symbols and returns those symbols sorted according to the positional value of each symbol and joined as a single string.

Parameters:

vector – The sum vector that should be resolved into a symbol term

get_symbols(vector: Tuple[int, ...]) Tuple[str, ...]

Returns a sorted, minimal tuple of symbols whose combined value together with the offset result in the given sum.

Raises:

SymbolValueNotMapped – If the value can not be represented by any combination of symbols in the arithmetic

Parameters:

vector – The sum vector that should be resolved into a symbol term

get_vector(symbol_str: str) Tuple[int, ...]

Returns the vector integer sum (adjusted for offset, if set) for a given symbol string.

Raises:

UnknownSymbolString – If arithmetic did not match the string

Parameters:

symbol_str – A string consisting of symbols defined in this arithmetic

get_vector_from_symbols(symbols: Tuple[str, ...]) Tuple[int, ...]

Returns the vector integer sum (adjusted for offset, if set) for a given tuple of parsed symbol literals

Parameters:

symbols – A tuple with each element being a symbol literal in this arithmetic

parse(symbol_str: str) Tuple[str, ...]

Parses a symbol string into a list of symbols

>>> from xenharmlib.core.symbols import SymbolArithmetic
>>> arithmetic = SymbolArithmetic(dimensions=2)
>>> arithmetic.add_symbol('x', (2, 0))
>>> arithmetic.add_symbol('#', (1, 0))
>>> arithmetic.add_symbol('b', (-1, 0))
>>> arithmetic.add_symbol('^', (0, 1))
>>> symbols = arithmetic.parse('xbb#')
>>> symbols
('x', 'b', 'b', '#')
Raises:

UnknownSymbolString – If arithmetic did not match the string

Parameters:

symbol_str – A symbol string consisting of symbols defined in this arithmetic

class xenharmlib.core.symbols.SymbolArithmeticSet(dimensions: int = 1, pref_func: Callable[[List[Tuple[SymbolArithmetic, Tuple[str, ...]]]], Tuple[SymbolArithmetic, Tuple[str, ...]]] | None = None)

SymbolArithmeticSets combine different SymbolArithmetics allowing to use multiple symbols for the same integer vector and to segment the space of integer vectors into multiple arithmetics with different offsets.

You can for example combine four arithmetics to represent traditional interval naming of imperfect intervals:

  • ‘M’ represents vector (0, 0)

  • ‘^M’ represents vector (0, 1)

  • ‘A’ represents vector (2, 0)

  • ‘m’ represents vector (-1, 0)

  • ‘d’ represents vector (-2, 0)

  • ‘vd’ represents vector (-2, -1)

Parameters:
  • dimensions – The dimensions of the arithmetics in the set (optional, defaults to 1)

  • pref_func – (optional) A preference function that returns a definite parsing result from a list of possible ones. The function should accept a list of tuples (arithmetic, parsed_str) with parsed_str being a tuple of single symbols. It should return one element of the list that should be preferred. If no preference function is given, then the class will choose the result with the shortest length.

add_arithmetic(arithmetic: SymbolArithmetic)

Adds another symbol arithmetic to this set

Parameters:

arithmetic – The arithmetic to add

property dimensions: int

The vector dimensions of arithmetics in this set

get_symbol_str(vector: Tuple[int, ...]) str

Returns a minimal symbol string for a given value

Raises:

SymbolValueNotMapped – If the value can not be represented by any combination of symbols in any arithmetic

Parameters:

value – A positive or negative integer

get_vector(symbol_str: str) Tuple[int, ...]

Returns the vector sum value for a given string

Raises:

UnknownSymbolString – If no arithmetic in the set matched the string

Parameters:

symbol_str – A symbol string consisting of symbols defined by at least one arithmetic in the set.

parse(symbol_str: str) Tuple[SymbolArithmetic, Tuple[str, ...]]

Tries to parse a symbol string by each arithmetic in the set. If an arithmetic returns a result it is added to the list of possible results from which then subsequently one result is selected using the preference function given during set initialization.

The function returns a tuple (arithmetic, symbols) with the first element being the chosen arithmetic and the second being the parsing result from that arithmetic.

Raises:

UnknownSymbolString – If no arithmetic in the set matched the string

class xenharmlib.core.symbols.SymbolCode

SymbolCode defines a general interface for different strategies to turn symbol strings into integer vectors and vice versa.

The interface consists of two abstract methods
abstractmethod get_symbol_str(vector: Tuple[int, ...]) str

Abstract method placeholder for a specific implementation to convert an integer vector into a symbol or sequence of symbols

Parameters:

vector – An integer vector

Raises:

SymbolValueNotMapped – If mapping has no ruleset to convert the vector into a string

abstractmethod get_vector(symbol_str: str) Tuple[int, ...]

Abstract method placeholder for a specific implementation to convert a string of one or more symbols into an integer vector

Parameters:

string – A string consisting of one or more symbols

Raises:

UnknownSymbolString – If mapping has no ruleset to convert the string into an integer vector

exception xenharmlib.core.symbols.SymbolValueNotMapped

Gets raised whenever an integer value is not mapped by a word in a symbol code

exception xenharmlib.core.symbols.UnfittingDimensions

Gets raised whenever a vector does not fit to the dimension configuration of the symbol code

exception xenharmlib.core.symbols.UnknownSymbolString

Gets raised whenever a SymbolCode receives a string that is not part of its grammar

Exceptions

This module includes all exceptions that must be handled by the user of the library

exception xenharmlib.exc.IncompatibleOriginContexts

Gets raised whenever two or more objects are not compatible because they are based on different orgin contexts

exception xenharmlib.exc.InvalidAccidentalValue

Gets raised when an accidental value is not allowed in a notation

exception xenharmlib.exc.InvalidBaseIntervalIndex

Gets raised when a base interval index does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.InvalidFrequency

Gets raised when a frequency argument does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.InvalidGenerator

Gets raised when a given pitch or pitch-like argument is not a generator in respect to the tuning

exception xenharmlib.exc.InvalidIndexMask

Gets raised when an index mask expression is invalid

exception xenharmlib.exc.InvalidIntervalNumber

Gets raised when an interval number is not valid

exception xenharmlib.exc.InvalidNaturalDiffClassIndex

Gets raised when a natural diff class index does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.InvalidNaturalIndex

Gets raised when a natural index does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.InvalidPitchClassIndex

Gets raised when a pitch class index does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.InvalidPitchIndex

Gets raised when a pitch index does not adhere to a certain restriction, for example if it is out of bounds of a predefined limit

exception xenharmlib.exc.UnfittingNotation

Gets raised on construction of notations when a property of the tuning prohibits the use of the specific notation

exception xenharmlib.exc.UnknownNoteSymbol

Gets raised on construction of notes if a provided symbol was not recognized by the notation