Skip to content

Commit

Permalink
Fix: distance in adjacent octaves (#440)
Browse files Browse the repository at this point in the history
* fix: adjacent octaves enharmonics

* chore: changeset
  • Loading branch information
danigb authored Jul 23, 2024
1 parent b113754 commit 4e05792
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 36 deletions.
6 changes: 6 additions & 0 deletions .changeset/lazy-deers-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@tonaljs/pitch-distance": patch
"tonal": patch
---

Fix a bug finding distance between notes when they are in adjacent octaves (see #428)
5 changes: 3 additions & 2 deletions packages/pitch-distance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,12 @@ export function distance(
? tcoord[1] - fcoord[1]
: -Math.floor((fifths * 7) / 12);

// If it's unison and not pitch class, it can be descending interval (#243)
// If it's unison, not pitch class, and in the same octave
// it can be descending interval (see #243 & #428)
const forceDescending =
to.height === from.height &&
to.midi !== null &&
from.midi !== null &&
from.oct === to.oct &&
from.step > to.step;
return coordToInterval([fifths, octs], forceDescending).name;
}
68 changes: 37 additions & 31 deletions packages/pitch-distance/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,42 @@ const allIntervalsFrom = (from: string) => (str: string) =>
.join(" ");

describe("distance", () => {
describe("find intervals between notes", () => {
test("interval between notes", () => {
const fromC3 = allIntervalsFrom("C3");
expect(fromC3("C3 e3 e4 c2 e2")).toEqual("1P 3M 10M -8P -6m");
});

test("unison interval edge case #243", () => {
expect(distance("Db4", "C#5")).toEqual("7A");
expect(distance("Db4", "C#4")).toEqual("-2d");
expect(distance("Db", "C#")).toEqual("7A");
expect(distance("C#", "Db")).toEqual("2d");
});

test("intervals between pitch classes are always ascending", () => {
expect(distance("C", "D")).toEqual("2M");

const fromC = allIntervalsFrom("C");
expect(fromC("c d e f g a b")).toEqual("1P 2M 3M 4P 5P 6M 7M");

const fromG = allIntervalsFrom("G");
expect(fromG("c d e f g a b")).toEqual("4P 5P 6M 7m 1P 2M 3M");
});

test("if a note is a pitch class, the distance is between pitch classes", () => {
expect(distance("C", "C2")).toBe("1P");
expect(distance("C2", "C")).toBe("1P");
});

test("notes must be valid", () => {
expect(distance("one", "two")).toBe("");
});
test("interval between notes", () => {
const fromC3 = allIntervalsFrom("C3");
expect(fromC3("C3 e3 e4 c2 e2")).toEqual("1P 3M 10M -8P -6m");
});

test("unison interval edge case #243", () => {
expect(distance("Db4", "C#5")).toEqual("7A");
expect(distance("Db4", "C#4")).toEqual("-2d");
expect(distance("Db", "C#")).toEqual("7A");
expect(distance("C#", "Db")).toEqual("2d");
});

test("adjacent octaves #428", () => {
expect(distance("B#4", "C4")).toBe("-7A");
expect(distance("B#4", "C6")).toBe("9d");
expect(distance("B#4", "C5")).toBe("2d");
expect(distance("B##4", "C#5")).toBe("2d");
expect(distance("B#5", "C6")).toBe("2d");
});

test("intervals between pitch classes are always ascending", () => {
expect(distance("C", "D")).toEqual("2M");

const fromC = allIntervalsFrom("C");
expect(fromC("c d e f g a b")).toEqual("1P 2M 3M 4P 5P 6M 7M");

const fromG = allIntervalsFrom("G");
expect(fromG("c d e f g a b")).toEqual("4P 5P 6M 7m 1P 2M 3M");
});

test("if a note is a pitch class, the distance is between pitch classes", () => {
expect(distance("C", "C2")).toBe("1P");
expect(distance("C2", "C")).toBe("1P");
});

test("notes must be valid", () => {
expect(distance("one", "two")).toBe("");
});
});
2 changes: 1 addition & 1 deletion packages/tonal/browser/tonal.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/tonal/browser/tonal.min.js.map

Large diffs are not rendered by default.

0 comments on commit 4e05792

Please sign in to comment.