Skip to content

Pitch

This page details the Pitch class and all its methods.

There are three main ways to create Pitch vectors from scratch. Using the class constructor, using the static method Pitch.fromChroma, or using static methods on a parse class to parse a Pitch from a string format like SPN or LilyPond.

constructor(w: number, h: number);

Internally a pitch is defined as some number of whole steps and some number of half steps from C1\sf{C}_{-1} (the lowest MIDI note). You can directly initialise a Pitch like so:

let p = new Pitch(25, 10); // coordinates for C4
p.w; // 25
p.h; // 10
static fromChroma(chroma: number, octave: number): Pitch;

This method allows you to initialise a Pitch from its “chroma”, the signed distance of a note from C in perfect 5ths, and its octave using SPN numbering:

let p = Pitch.fromChroma(0, 4);
p.w; // 25
p.h; // 10

The following methods extract information from a Pitch vector.

get midi(): number;

The standard MIDI number of a Pitch. Throws an error if outside of the MIDI range of C1\sf{C}_{-1} to G9\sf{G}_9:

let p = SPN.toPitch("C4");
p.midi; // 60
p = SPN.toPitch("C-1");
p.midi; // 0
p = SPN.toPitch("G9");
p.midi; // 127
p = SPN.toPitch("A-2");
p.midi; // Error: Outside of standard MIDI range: -3
p = SPN.toPitch("A9");
p.midi; // Error: Outside of standard MIDI range: 129
get chroma(): number;

The signed distance of a Pitch from C in perfect fifths.

let p = SPN.toPitch("D3");
p.chroma; // 2, because C G D => 0 1 2
p = SPN.toPitch("Eb5");
p.chroma; // -3, because Eb Bb F C => -3 -2 -1 0
get pc7(): number;

The 0-indexed 7-tone pitch class of a Pitch. Equivalent to a numerical representation of its letter name, where C is 0:

let p = SPN.toPitch("C4");
p.pc7; // 0
p = SPN.toPitch("F4");
p.pc7; // 3
get pc12(): number;

The 12-tone pitch class of a note. C is 0.

let p = SPN.toPitch("C4");
p.pc12; // 0
p = SPN.toPitch("E4");
p.pc12; // 4
p = SPN.toPitch("Fb4");
p.pc12; // also 4, due to enharmonicity in 12TET
get letter(): string;

The letter component of a Pitch vector’s standard name.

let p = SPN.toPitch("E4");
p.letter; // "E"
get accidental(): number;

The accidental component of a Pitch vector’s standard name, expressed as a signed integer.

  • 0 means natural.
  • +1 means sharp.
  • -1 means flat.
  • +2 means double-sharp.
  • -2 means double-flat.
  • etc. for any arbitrary accidental.
let p = SPN.toPitch("Fx");
p.accidental; // 2
p = SPN.toPitch("Eb");
p.accidental; // -1
p = SPN.toPitch("Abbb");
p.accidental; // -3
get octave(): number;

The octave number of a Pitch (in SPN numbering).

let p = SPN.toPitch("F4");
p.octave; // 4
stepsTo(p: Pitch): number;

Returns the (signed) number of diatonic steps separating a Pitch from another passed-in Pitch.

let p = SPN.toPitch("C4");
let q = SPN.toPitch("F#4");
p.stepsTo(q); // 3
q = SPN.toPitch("Ab3");
p.stepsTo(q); // -2
isEqual(p: Pitch): boolean;

Returns true if and only if the passed in Pitch vector and the current vector are identical. Note that this does not mean “are enharmonically equivalent in 12TET”, or “have the same pitch chroma”: they must literally hold the same coordinates.

let p = SPN.toPitch("C4");
let q = SPN.toPitch("C5");
p.isEqual(q); // false
q = SPN.toPitch("B3");
p.isEqual(q); // false
q = SPN.toPitch("C4");
p.isEqual(q); // true
isEnharmonic(p: Pitch, edo?: number): boolean;

Returns true if the passed in Pitch is enharmonic to the current Pitch in the passed in EDO tuning. If no second argument is passed this method defaults to 12TET. Notes will still register as enharmonic if they are in different octaves.

let p = SPN.toPitch("C#4");
let q = SPN.toPitch("Db4");
p.isEnharmonic(q); // true (in 12TET)
p.isEnharmonic(q, 31); // false (in 31EDO)
p = SPN.toPitch("Gbb4");
q = SPN.toPitch("Ex4");
p.isEnharmonic(q); // false (in 12TET)
p.isEnharmonic(q, 31); // true (in 31EDO)
degreeIn(context: TonalContext): number;

Returns the scale degree number (0-indexed, such that the tonic degree is 0) represented by the Pitch in the passed-in TonalContext:

let context = TonalContext.fromStrings("C", "major");
let p = SPN.toPitch("C4");
p.degreeIn(context); // 0
p = SPN.toPitch("D4");
p.degreeIn(context); // 1
p = SPN.toPitch("D#4");
p.degreeIn(context); // still 1 (just an altered variant)
alterationIn(context: TonalContext): number;

Returns the alteration represented by the Pitch in the passed-in TonalContext.

  • 0 represents a diatonic degree.
  • +1 and -1 represent raised and lowered degrees respectively.
  • +2 and -2 represent degrees too sharp or too flat to belong in a given TonalContext.
let context = TonalContext.fromStrings("G", "minor");
let p = SPN.toPitch("Bb4")
p.alterationIn(context); // 0, Bb is diatonic in D minor
p = SPN.toPitch("B4")
p.alterationIn(context); // 1, B is raised in D minor
p = SPN.toPitch("Bbb4")
p.alterationIn(context); // -2, Bbb is too flat for this context

The following methods produce a new vector from the current Pitch. None of them mutate the original object.

intervalTo(p: Pitch): Interval;

Returns the Interval from the current Pitch to another passed-in vector. Often a more convenient way to access Interval.between

let p = SPN.toPitch("C4");
let q = SPN.toPitch("E4");
let m = p.intervalTo(q); // m now holds a major third Interval
let n = Interval.between(p, q); // equivalent
transposeReal(m: Interval): Pitch;

Transposes the underlying Pitch by the passed in Interval vector. Returns the transposed Pitch as a new vector:

let p = SPN.toPitch("C4");
let q = SPN.toPitch("E4");
let m = Interval.fromName("M3");
p = p.transposeReal(m);
p.isEqual(q); // true
invert(axis: Axis): Pitch;

Invert a Pitch about the passed in Axis. An Axis is created from two Pitches that will be mapped to each other by the inversion across it. Returns the inverted Pitch as a new vector.

let axis = Axis.fromSPN("C4", "G4");
let p = SPN.toPitch("Db4");
p = p.invert(axis); // p now points to F#4
snapTo(context: TonalContext): Pitch;

Snaps a Pitch vector to the diatonic position for that letter-name in the passed-in TonalContext. Returns the result as a new Pitch:

let context = TonalContext.fromStrings("C", "major");
let p = SPN.toPitch("F#4");
p = p.snapTo(context); // p now points to F4
transposeDiatonic(steps: number, context: TonalContext): Pitch;

Transposes a Pitch by a generic interval, snapping to diatonic values.

  • Interval measured in steps, such that 0 is a unison.
let context = TonalContext.fromStrings("C", "major");
let p = SPN.toPitch("F#4");
p = p.transposeDiatonic(4, context); // p now points to C5
diatonic(from: Pitch, to: Pitch, context: TonalContext): Generator<Pitch, void, unknown>;

Generates a diatonic range of Pitch vectors between the two boundary Pitches passed-in, within the specified TonalContext

let context = TonalContext.fromStrings("C", "major");
let p = SPN.toPitch("C4");
let q = SPN.toPitch("E5");
Pitch.range.diatonic(p, q, context).forEach(r => console.log(SPN.fromPitch(r)));
// C4 D4 E4 F4 G4 A4 B4 C5 D5 E5
chromatic(from: Pitch, to: Pitch, context: TonalContext): Generator<Pitch, void, unknown>;

Generates a chromatic range of Pitch vectors between the two boundary Pitches passed-in, within the specified TonalContext. Essentially any all pitches between the boundaries that could occur diatonically or chromatically in a given tonal context.

let context = TonalContext.fromStrings("C", "major");
let p = SPN.toPitch("C4");
let q = SPN.toPitch("E5");
Pitch.range.chromatic(p, q, context).forEach(r => console.log(SPN.fromPitch(r)));
// C4 Db4 C#4 D4 Eb4 D#4 E4 F4 Gb4 F#4 G4 Ab4 G#4 A4 Bb4 A#4 B4 C5 Db5 C#5 D5 Eb5 D#5 E5