The Generic Interface

Overview

Handling Intervals

The operations of the generic interface are based on intervals as the fundamental elements. Intervals can be thought of as vectors in a vector space (or more precisely: a module over integers). They can be added, subtracted, negated, and multiplied with integers. Pitches, on the other hand, can be seen as points in this space and are represented as intervals in relation to an (implicit) origin. Therefore, pitch types are mainly defined as a wrapper type Pitch{Interval} that generically defines its arithmetic operations in terms of the corresponding interval type.

Interval types (here denoted as I) define the following operations:

  • I + I
  • I - I
  • -I
  • I * Integer
  • Integer * I
  • sign(I)
  • abs(I)

The sign indicates the logical direction of the interval by musical convention (upward = positive, downward = negative), even if the interval space is multi-dimensional. Consequently, abs ensures that an interval is neutral or upward-directed. For interval classes (which are generally undirected), the sign indicates the direction of the "shortest" class member:

julia> sign(i"P4")
1

julia> sign(i"P5") # == -i"P4"
-1

In addition to arithmetic operations, some special intervals are defined:

  • unison(Type{I}) / zero(Type{I})
  • octave(Type{I})
  • chromsemi(Type{I}) (a chromatic semitone, optional)
  • isstep(I) (optional, a predicate that test whether the interval is considered a "step")

Finally, some operations specify the relationship between intervals and interval classes:

  • ic(I): Returns the corresponding interval class.
  • embed(IC [, octs::Int]): Returns a canonical embedding of an interval class into interval space.
  • intervaltype(Type{IC}) = I
  • intervalclasstype(Type{I}) = IC

Handling Pitches

Pitch operations generally interact with intervals (and can be derived from the interval operations):

  • P + I -> P
  • I + P -> P
  • P - I -> P
  • P - P -> I
  • pc(P) -> PC
  • embed(PC [, octaves]) -> P

Other useful functions

Besides the specific functions of the interface, pitch and interval types generally implement basic functions such as

  • isless / <
  • isequal / ==
  • hash
  • show (usually also specialized for Pitch{I})

Note that the ordering of pitches is generally not unique, so isless uses an appropriate convention for each interval type.

Generic API Reference

Here we only list the new functions that are introduced by this library, not the ones that are already defined in Base.

Special Intervals

Pitches.unisonFunction
unison(T)

Returns the interval of a unison for interval type T. Alias for Base.zero. New interval types should implement Base.zero, but user code should call unison for better interpretability.

source
Pitches.octaveFunction
octave(T, [n=1])

Returns the interval corresponding to an octave for interval type T. For interval classes, this should return zero(T) (a default method is provided).

If n is specified, the octave is multiplied by n first. This is equivalent to octave(T) * n.

For convenience, a fallback for octave(p::T, [n]) is provided. Only octave(T) needs to be implemented.

source

Classes (Octave Equivalence)

Pitches.icFunction
ic(i)

Returns the interval class of an interval, removing the octave

source
Pitches.embedFunction
embed(ic, [oct=0])
embed(pc, [oct=0])

Converts an interval class to an interval in the canonical octave, adding oct octaves, if supplied. Also works for pitches.

source
Pitches.intervaltypeFunction
intervaltype(IC::Type)

Returns for an interval class type IC the corresponding interval type. For convenience, intervaltype(ic::IC) is also provided.

source
Pitches.intervalclasstypeFunction
intervalclasstype(I::Type)

Returns for an interval type I the corresponding interval class type. For convenience, intervalclasstype(p::P) is also provided.

source