Pitch
This page details the Pitch class and all its methods.
Creating Pitches
Section titled “Creating Pitches”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.
Class Constructor
Section titled “Class Constructor”constructor(w: number, h: number);Internally a pitch is defined as some number of whole steps and some number of half steps from (the lowest MIDI note). You can directly initialise a Pitch like so:
let p = new Pitch(25, 10); // coordinates for C4
p.w; // 25p.h; // 10fromChroma
Section titled “fromChroma”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; // 25p.h; // 10Common Queries
Section titled “Common Queries”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 to :
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: 129chroma
Section titled “chroma”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 0get 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; // 3get 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 12TETletter
Section titled “letter”get letter(): string;The letter component of a Pitch vector’s standard name.
let p = SPN.toPitch("E4");p.letter; // "E"accidental
Section titled “accidental”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; // -3octave
Section titled “octave”get octave(): number;The octave number of a Pitch (in SPN numbering).
let p = SPN.toPitch("F4");p.octave; // 4intervalTo
Section titled “intervalTo”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 Intervallet n = Interval.between(p, q); // equivalentstepsTo
Section titled “stepsTo”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); // -2isEqual
Section titled “isEqual”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); // trueisEnharmonic
Section titled “isEnharmonic”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
Section titled “degreeIn”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
Section titled “alterationIn”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 contexthighest
Section titled “highest”highest(arr: Pitch[], T?: TuningMap): Pitch;Returns the highest Pitch in a passed-in array. Uses an optional TuningMap to determine which Pitch is higher than the others; if no TuningMap is passed in, defaults to 12TET.
const pitchArray = ["C4", "F#4", "D4", "Bb4", "A#4", "G4"].map(p => SPN.toPitch(p));
const highest = Pitch.highest(pitchArray); // highest holds Bb4lowest
Section titled “lowest”lowest(arr: Pitch[], T?: TuningMap): Pitch;Returns the lowest Pitch in a passed-in array. Uses an optional TuningMap to determine which Pitch is lower than the others; if no TuningMap is passed in, defaults to 12TET.
const pitchArray = ["C4", "F#4", "D4", "Bb4", "A#4", "G4"].map(p => SPN.toPitch(p));
const lowest = Pitch.lowest(pitchArray); // lowest holds C4nearest
Section titled “nearest”nearest(arr: Pitch[], T?: TuningMap): Pitch;Returns the nearest Pitch in a passed-in array to the calling Pitch instance. Uses an optional TuningMap to determine which Pitch is nearer than the others; if no TuningMap is passed in, defaults to 12TET.
const pitchArray = ["C4", "F#4", "D4", "Bb4", "A#4", "G4"].map(p => SPN.toPitch(p));let p = SPN.toPitch("Eb4");
const nearest = p.nearest(pitchArray); // nearest holds D4Transformations
Section titled “Transformations”The following methods produce a new Pitch from the current Pitch. None of them mutate the original object.
transposeReal
Section titled “transposeReal”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); // trueinvert
Section titled “invert”invert(axis: MirrorAxis): Pitch;Invert a Pitch about the passed in MirrorAxis. A MirrorAxis is created from two Pitches that will be mapped to each other by the inversion across it, or via the Axis.fromSPN method using SPN strings. Returns the inverted Pitch as a new vector.
let axis = MirrorAxis.fromSPN("C4", "G4");let p = SPN.toPitch("Db4");
p = p.invert(axis); // p now points to F#4snapTo
Section titled “snapTo”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 F4transposeDiatonic
Section titled “transposeDiatonic”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 C5Ranges
Section titled “Ranges”range.diatonic
Section titled “range.diatonic”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 E5range.chromatic
Section titled “range.chromatic”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