@tonaljs/chord 5.0.3 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,62 +18,70 @@ const { Chord } = require("tonal");
18
18
 
19
19
  #### `Chord.getChord(type: string, tonic?: string, root?: string) => Chord`
20
20
 
21
- Get the chord properties from a chord type and an (optional) tonic and (optional) root. Notice that the tonic must be present if the root is present. Also the root must be part of the chord notes.
21
+ #### `Chord.get(name: string | [string, string] | [string, string, string]) => Chord`
22
22
 
23
- It returns the same object that `ChordType.get` but with additional properties:
23
+ Given a chord symbol or tokens, it returns the chord properties.
24
24
 
25
- - symbol: the chord symbol (a combiation of the tonic, chord type shortname and root, if present). For example: `Cmaj7`, `Db7b5/F`. The symbol always uses pitch classes (note names without octaves) for both the tonic and root.
25
+ Chord properties is the the same object that `ChordType.get` but with additional fields:
26
+
27
+ - symbol: the chord symbol (a combination of the tonic, chord type shortname and root, if present). For example: `Cmaj7`, `Db7b5/F`. The symbol always uses pitch classes (note names without octaves) for both the tonic and root.
26
28
  - tonic: the tonic of the chord (or an empty string if not present)
27
- - root: the root of the chord (or an empty string if not present)
28
- - rootDegree: the degree of the root. 0 if root not present. A number greater than 0 if present, where 1 indicates the tonic, 2 the second note (normally the 3th), 2 the third note (normally the 5th), etc.
29
- - notes: an array of notes, or empty array if tonic is not present. If the root is pres
29
+ - bass: the bass of the chord (or an empty string if not present). The bass can be any pitch class.
30
+ - root: the root of the chord (or an empty string if not present). The root is present if the bass not belongs to the chord. It could be chords with bass without root field, but not the opposite.
31
+ - rootDegree: the degree of the root. NaN if root not present. A number greater than 0 if present, where 1 indicates the tonic, 2 the second note (normally the 3th), 2 the third note (normally the 5th), etc.
32
+ - notes: an array of notes, or empty array if tonic is not present. The notes will be always pitch classes.
30
33
 
31
34
  Example:
32
35
 
33
36
  ```js
34
- Chord.getChord("maj7", "G4", "B4"); // =>
37
+ Chord.get("Cmaj7/B"); // =>
35
38
  // {
36
39
  // empty: false,
37
- // name: "G major seventh over B",
38
- // symbol: "Gmaj7/B",
39
- // tonic: "G4",
40
- // root: "B4",
41
- // rootDegree: 2,
40
+ // name: 'C major seventh over B',
42
41
  // setNum: 2193,
43
- // type: "major seventh",
44
- // aliases: ["maj7", "Δ", "ma7", "M7", "Maj7"],
45
- // chroma: "100010010001",
46
- // intervals: ["3M", "5P", "7M", "8P"],
47
- // normalized: "100010010001",
48
- // notes: ["B4", "D5", "F#5", "G5"],
49
- // quality: "Major",
42
+ // chroma: '100010010001',
43
+ // normalized: '100010010001',
44
+ // intervals: [ '7M', '8P', '10M', '12P' ],
45
+ // quality: 'Major',
46
+ // aliases: [ 'maj7', 'Δ', 'ma7', 'M7', 'Maj7', '^7' ],
47
+ // symbol: 'Cmaj7/B',
48
+ // tonic: 'C',
49
+ // type: 'major seventh',
50
+ // root: 'B',
51
+ // bass: 'B',
52
+ // rootDegree: 4,
53
+ // notes: [ 'B', 'C', 'E', 'G' ]
50
54
  // }
51
55
  ```
52
56
 
53
- #### `Chord.get(name: string | [string, string]) => Chord`
57
+ `Chord.chord` is an alias that is handy if using the `@tonaljs/chord` directly:
58
+
59
+ ```js
60
+ import { chord } from "@tonaljs/chord";
61
+
62
+ chord("C6add2");
63
+ ```
54
64
 
55
- An alias of `Chord.getChord` but accepts a chord symbol as parameter.
65
+ `Chord.getChord(chordType, tonic, bass)` is very similar but with arguments for each chord part:
56
66
 
57
67
  ```js
58
- Chord.get("Cmaj7");
59
- // same as
60
- Chord.get(["C", "maj7"]);
61
- // same as
62
- Chord.getChord("maj7", "C");
68
+ Chord.getChord("maj7", "C", "B") === Chord.get("Cmaj7/B");
63
69
  ```
64
70
 
65
- Important: currently chord with bass are NOT allowed (will be implemented in next version):
71
+ ### `Chord.notes(chordType: string, tonic?: string) => string[]`
72
+
73
+ Print the notes of the given chord at the given tonic:
66
74
 
67
75
  ```js
68
- Chord.get("Cmaj7/E"); // => { empty: true }
76
+ Chord.notes("maj4", "C4"); // => ["C4", "E4", "G4", "B4"]
69
77
  ```
70
78
 
71
- ### `Chord.degrees(chordName: string | [string, string]) => (degree: number) => string`
79
+ ### `Chord.degrees(chordType: string, tonic?: string) => (degree: number) => string`
72
80
 
73
81
  `Scale.degrees` returns a function to get a note name from a scale degree:
74
82
 
75
83
  ```js
76
- const c4m7 = Chord.degrees(["C4", "m7");
84
+ const c4m7 = Chord.degrees("m7", "C4");
77
85
  c4m7(1); // => "C4"
78
86
  c4m7(2); // => "Eb4"
79
87
  c4m7(3); // => "G4"
@@ -81,13 +89,13 @@ c4m7(4); // => "Bb4"
81
89
  c4m7(1); // => "C5"
82
90
  ```
83
91
 
84
- It can be used to find chord inversions:
92
+ It can be used, for example, to get the notes of chord inversions:
85
93
 
86
94
  ```js
87
- [1, 2, 3, 4].map(chord); // => ["C4", "Eb4", "G4", "Bb4"]
88
- [2, 3, 4, 5].map(chord); // => ["Eb4", "G4", "Bb4", "C5"]
89
- [3, 4, 5, 6].map(chord); // => ["G4", "Bb4", "C5", "Eb5"]
90
- [4, 5, 6, 7].map(chord); // => ["Bb4", "C5", "Eb5", "G5"]
95
+ [1, 2, 3, 4].map(c4m7); // => ["C4", "Eb4", "G4", "Bb4"]
96
+ [2, 3, 4, 5].map(c4m7); // => ["Eb4", "G4", "Bb4", "C5"]
97
+ [3, 4, 5, 6].map(c4m7); // => ["G4", "Bb4", "C5", "Eb5"]
98
+ [4, 5, 6, 7].map(c4m7); // => ["Bb4", "C5", "Eb5", "G5"]
91
99
  ```
92
100
 
93
101
  Bear in mind that degree numbers starts with 1 and 0 returns an empty string:
package/dist/index.d.mts CHANGED
@@ -3,27 +3,30 @@ export { detect } from '@tonaljs/chord-detect';
3
3
  import { ChordType } from '@tonaljs/chord-type';
4
4
  import { NoteName } from '@tonaljs/pitch-note';
5
5
 
6
- declare function deprecate<ResultFn extends (this: any, ...newArgs: any[]) => ReturnType<ResultFn>>(original: string, alternative: string, fn: ResultFn): (this: unknown, ...args: unknown[]) => ReturnType<ResultFn>;
7
- type ChordName = string;
8
- type ChordNameTokens = [string, string];
6
+ type ChordNameOrTokens = string | [string] | [string, string] | [string, string, string];
7
+ type ChordNameTokens = [string, string, string];
9
8
  interface Chord extends ChordType {
10
9
  tonic: string | null;
11
10
  type: string;
12
11
  root: string;
12
+ bass: string;
13
13
  rootDegree: number;
14
14
  symbol: string;
15
15
  notes: NoteName[];
16
16
  }
17
17
  /**
18
- * Tokenize a chord name. It returns an array with the tonic and chord type
18
+ * Tokenize a chord name. It returns an array with the tonic, chord type and bass
19
19
  * If not tonic is found, all the name is considered the chord name.
20
20
  *
21
21
  * This function does NOT check if the chord type exists or not. It only tries
22
22
  * to split the tonic and chord type.
23
23
  *
24
+ * This function does NOT check if the bass is part of the chord or not but it
25
+ * only accepts a pitch class as bass
26
+ *
24
27
  * @function
25
28
  * @param {string} name - the chord name
26
- * @return {Array} an array with [tonic, type]
29
+ * @return {Array} an array with [tonic, type, bass]
27
30
  * @example
28
31
  * tokenize("Cmaj7") // => [ "C", "maj7" ]
29
32
  * tokenize("C7") // => [ "C", "7" ]
@@ -34,7 +37,7 @@ declare function tokenize(name: string): ChordNameTokens;
34
37
  /**
35
38
  * Get a Chord from a chord name.
36
39
  */
37
- declare function get(src: ChordName | ChordNameTokens): Chord;
40
+ declare function get(src: ChordNameOrTokens): Chord;
38
41
  /**
39
42
  * Get chord properties
40
43
  *
@@ -42,8 +45,8 @@ declare function get(src: ChordName | ChordNameTokens): Chord;
42
45
  * @param [tonic] - Optional tonic
43
46
  * @param [root] - Optional root (requires a tonic)
44
47
  */
45
- declare function getChord(typeName: string, optionalTonic?: string, optionalRoot?: string): Chord;
46
- declare const chord: (this: unknown, ...args: unknown[]) => Chord;
48
+ declare function getChord(typeName: string, optionalTonic?: string, optionalBass?: string): Chord;
49
+ declare const chord: typeof get;
47
50
  /**
48
51
  * Transpose a chord name
49
52
  *
@@ -79,6 +82,10 @@ declare function extended(chordName: string): string[];
79
82
  * @example
80
83
  */
81
84
  declare function reduced(chordName: string): string[];
85
+ /**
86
+ * Return the chord notes
87
+ */
88
+ declare function notes(chordName: ChordNameOrTokens, tonic?: string): string[];
82
89
  /**
83
90
  * Returns a function to get a note name from the scale degree.
84
91
  *
@@ -86,11 +93,12 @@ declare function reduced(chordName: string): string[];
86
93
  * [1, 2, 3, 4].map(Chord.degrees("C")) => ["C", "E", "G", "C"]
87
94
  * [1, 2, 3, 4].map(Chord.degrees("C4")) => ["C4", "E4", "G4", "C5"]
88
95
  */
89
- declare function degrees(chordName: string | ChordNameTokens): (degree: number) => string;
96
+ declare function degrees(chordName: ChordNameOrTokens, tonic?: string): (degree: number) => string;
90
97
  /**
91
98
  * Sames as `degree` but with 0-based index
92
99
  */
93
- declare function steps(chordName: string | ChordNameTokens): (normalized: number) => string;
100
+ declare function steps(chordName: ChordNameOrTokens, tonic?: string): (normalized: number) => string;
101
+ /** @deprecated */
94
102
  declare const _default: {
95
103
  getChord: typeof getChord;
96
104
  get: typeof get;
@@ -102,7 +110,8 @@ declare const _default: {
102
110
  transpose: typeof transpose;
103
111
  degrees: typeof degrees;
104
112
  steps: typeof steps;
105
- chord: (this: unknown, ...args: unknown[]) => Chord;
113
+ notes: typeof notes;
114
+ chord: typeof get;
106
115
  };
107
116
 
108
- export { type Chord, chord, chordScales, _default as default, degrees, deprecate, extended, get, getChord, reduced, steps, tokenize, transpose };
117
+ export { type Chord, chord, chordScales, _default as default, degrees, extended, get, getChord, notes, reduced, steps, tokenize, transpose };
package/dist/index.d.ts CHANGED
@@ -3,27 +3,30 @@ export { detect } from '@tonaljs/chord-detect';
3
3
  import { ChordType } from '@tonaljs/chord-type';
4
4
  import { NoteName } from '@tonaljs/pitch-note';
5
5
 
6
- declare function deprecate<ResultFn extends (this: any, ...newArgs: any[]) => ReturnType<ResultFn>>(original: string, alternative: string, fn: ResultFn): (this: unknown, ...args: unknown[]) => ReturnType<ResultFn>;
7
- type ChordName = string;
8
- type ChordNameTokens = [string, string];
6
+ type ChordNameOrTokens = string | [string] | [string, string] | [string, string, string];
7
+ type ChordNameTokens = [string, string, string];
9
8
  interface Chord extends ChordType {
10
9
  tonic: string | null;
11
10
  type: string;
12
11
  root: string;
12
+ bass: string;
13
13
  rootDegree: number;
14
14
  symbol: string;
15
15
  notes: NoteName[];
16
16
  }
17
17
  /**
18
- * Tokenize a chord name. It returns an array with the tonic and chord type
18
+ * Tokenize a chord name. It returns an array with the tonic, chord type and bass
19
19
  * If not tonic is found, all the name is considered the chord name.
20
20
  *
21
21
  * This function does NOT check if the chord type exists or not. It only tries
22
22
  * to split the tonic and chord type.
23
23
  *
24
+ * This function does NOT check if the bass is part of the chord or not but it
25
+ * only accepts a pitch class as bass
26
+ *
24
27
  * @function
25
28
  * @param {string} name - the chord name
26
- * @return {Array} an array with [tonic, type]
29
+ * @return {Array} an array with [tonic, type, bass]
27
30
  * @example
28
31
  * tokenize("Cmaj7") // => [ "C", "maj7" ]
29
32
  * tokenize("C7") // => [ "C", "7" ]
@@ -34,7 +37,7 @@ declare function tokenize(name: string): ChordNameTokens;
34
37
  /**
35
38
  * Get a Chord from a chord name.
36
39
  */
37
- declare function get(src: ChordName | ChordNameTokens): Chord;
40
+ declare function get(src: ChordNameOrTokens): Chord;
38
41
  /**
39
42
  * Get chord properties
40
43
  *
@@ -42,8 +45,8 @@ declare function get(src: ChordName | ChordNameTokens): Chord;
42
45
  * @param [tonic] - Optional tonic
43
46
  * @param [root] - Optional root (requires a tonic)
44
47
  */
45
- declare function getChord(typeName: string, optionalTonic?: string, optionalRoot?: string): Chord;
46
- declare const chord: (this: unknown, ...args: unknown[]) => Chord;
48
+ declare function getChord(typeName: string, optionalTonic?: string, optionalBass?: string): Chord;
49
+ declare const chord: typeof get;
47
50
  /**
48
51
  * Transpose a chord name
49
52
  *
@@ -79,6 +82,10 @@ declare function extended(chordName: string): string[];
79
82
  * @example
80
83
  */
81
84
  declare function reduced(chordName: string): string[];
85
+ /**
86
+ * Return the chord notes
87
+ */
88
+ declare function notes(chordName: ChordNameOrTokens, tonic?: string): string[];
82
89
  /**
83
90
  * Returns a function to get a note name from the scale degree.
84
91
  *
@@ -86,11 +93,12 @@ declare function reduced(chordName: string): string[];
86
93
  * [1, 2, 3, 4].map(Chord.degrees("C")) => ["C", "E", "G", "C"]
87
94
  * [1, 2, 3, 4].map(Chord.degrees("C4")) => ["C4", "E4", "G4", "C5"]
88
95
  */
89
- declare function degrees(chordName: string | ChordNameTokens): (degree: number) => string;
96
+ declare function degrees(chordName: ChordNameOrTokens, tonic?: string): (degree: number) => string;
90
97
  /**
91
98
  * Sames as `degree` but with 0-based index
92
99
  */
93
- declare function steps(chordName: string | ChordNameTokens): (normalized: number) => string;
100
+ declare function steps(chordName: ChordNameOrTokens, tonic?: string): (normalized: number) => string;
101
+ /** @deprecated */
94
102
  declare const _default: {
95
103
  getChord: typeof getChord;
96
104
  get: typeof get;
@@ -102,7 +110,8 @@ declare const _default: {
102
110
  transpose: typeof transpose;
103
111
  degrees: typeof degrees;
104
112
  steps: typeof steps;
105
- chord: (this: unknown, ...args: unknown[]) => Chord;
113
+ notes: typeof notes;
114
+ chord: typeof get;
106
115
  };
107
116
 
108
- export { type Chord, chord, chordScales, _default as default, degrees, deprecate, extended, get, getChord, reduced, steps, tokenize, transpose };
117
+ export { type Chord, chord, chordScales, _default as default, degrees, extended, get, getChord, notes, reduced, steps, tokenize, transpose };
package/dist/index.js CHANGED
@@ -24,11 +24,11 @@ __export(chord_exports, {
24
24
  chordScales: () => chordScales,
25
25
  default: () => chord_default,
26
26
  degrees: () => degrees,
27
- deprecate: () => deprecate,
28
27
  detect: () => import_chord_detect2.detect,
29
28
  extended: () => extended,
30
29
  get: () => get,
31
30
  getChord: () => getChord,
31
+ notes: () => notes,
32
32
  reduced: () => reduced,
33
33
  steps: () => steps,
34
34
  tokenize: () => tokenize,
@@ -37,22 +37,18 @@ __export(chord_exports, {
37
37
  module.exports = __toCommonJS(chord_exports);
38
38
  var import_chord_detect = require("@tonaljs/chord-detect");
39
39
  var import_chord_type = require("@tonaljs/chord-type");
40
+ var import_interval = require("@tonaljs/interval");
40
41
  var import_pcset = require("@tonaljs/pcset");
41
42
  var import_pitch_distance = require("@tonaljs/pitch-distance");
42
43
  var import_pitch_note = require("@tonaljs/pitch-note");
43
44
  var import_scale_type = require("@tonaljs/scale-type");
44
45
  var import_chord_detect2 = require("@tonaljs/chord-detect");
45
- function deprecate(original, alternative, fn) {
46
- return function(...args) {
47
- console.warn(`${original} is deprecated. Use ${alternative}.`);
48
- return fn.apply(this, args);
49
- };
50
- }
51
46
  var NoChord = {
52
47
  empty: true,
53
48
  name: "",
54
49
  symbol: "",
55
50
  root: "",
51
+ bass: "",
56
52
  rootDegree: 0,
57
53
  type: "",
58
54
  tonic: null,
@@ -67,68 +63,88 @@ var NoChord = {
67
63
  function tokenize(name) {
68
64
  const [letter, acc, oct, type] = (0, import_pitch_note.tokenizeNote)(name);
69
65
  if (letter === "") {
70
- return ["", name];
66
+ return tokenizeBass("", name);
67
+ } else if (letter === "A" && type === "ug") {
68
+ return tokenizeBass("", "aug");
69
+ } else {
70
+ return tokenizeBass(letter + acc, oct + type);
71
+ }
72
+ }
73
+ function tokenizeBass(note2, chord2) {
74
+ const split = chord2.split("/");
75
+ if (split.length === 1) {
76
+ return [note2, split[0], ""];
71
77
  }
72
- if (letter === "A" && type === "ug") {
73
- return ["", "aug"];
78
+ const [letter, acc, oct, type] = (0, import_pitch_note.tokenizeNote)(split[1]);
79
+ if (letter !== "" && oct === "" && type === "") {
80
+ return [note2, split[0], letter + acc];
81
+ } else {
82
+ return [note2, chord2, ""];
74
83
  }
75
- return [letter + acc, oct + type];
76
84
  }
77
85
  function get(src) {
78
- if (src === "") {
86
+ if (Array.isArray(src)) {
87
+ return getChord(src[1] || "", src[0], src[2]);
88
+ } else if (src === "") {
79
89
  return NoChord;
80
- }
81
- if (Array.isArray(src) && src.length === 2) {
82
- return getChord(src[1], src[0]);
83
90
  } else {
84
- const [tonic, type] = tokenize(src);
85
- const chord2 = getChord(type, tonic);
91
+ const [tonic, type, bass] = tokenize(src);
92
+ const chord2 = getChord(type, tonic, bass);
86
93
  return chord2.empty ? getChord(src) : chord2;
87
94
  }
88
95
  }
89
- function getChord(typeName, optionalTonic, optionalRoot) {
96
+ function getChord(typeName, optionalTonic, optionalBass) {
90
97
  const type = (0, import_chord_type.get)(typeName);
91
98
  const tonic = (0, import_pitch_note.note)(optionalTonic || "");
92
- const root = (0, import_pitch_note.note)(optionalRoot || "");
93
- if (type.empty || optionalTonic && tonic.empty || optionalRoot && root.empty) {
94
- return NoChord;
95
- }
96
- const rootInterval = (0, import_pitch_distance.distance)(tonic.pc, root.pc);
97
- const rootDegree = type.intervals.indexOf(rootInterval) + 1;
98
- if (!root.empty && !rootDegree) {
99
+ const bass = (0, import_pitch_note.note)(optionalBass || "");
100
+ if (type.empty || optionalTonic && tonic.empty || optionalBass && bass.empty) {
99
101
  return NoChord;
100
102
  }
103
+ const bassInterval = (0, import_pitch_distance.distance)(tonic.pc, bass.pc);
104
+ const bassIndex = type.intervals.indexOf(bassInterval);
105
+ const hasRoot = bassIndex >= 0;
106
+ const root = hasRoot ? bass : (0, import_pitch_note.note)("");
107
+ const rootDegree = bassIndex === -1 ? NaN : bassIndex + 1;
108
+ const hasBass = bass.pc && bass.pc !== tonic.pc;
101
109
  const intervals = Array.from(type.intervals);
102
- for (let i = 1; i < rootDegree; i++) {
103
- const num = intervals[0][0];
104
- const quality = intervals[0][1];
105
- const newNum = parseInt(num, 10) + 7;
106
- intervals.push(`${newNum}${quality}`);
107
- intervals.shift();
110
+ if (hasRoot) {
111
+ for (let i = 1; i < rootDegree; i++) {
112
+ const num = intervals[0][0];
113
+ const quality = intervals[0][1];
114
+ const newNum = parseInt(num, 10) + 7;
115
+ intervals.push(`${newNum}${quality}`);
116
+ intervals.shift();
117
+ }
118
+ } else if (hasBass) {
119
+ const ivl = (0, import_interval.subtract)((0, import_pitch_distance.distance)(tonic.pc, bass.pc), "8P");
120
+ if (ivl) intervals.unshift(ivl);
108
121
  }
109
- const notes = tonic.empty ? [] : intervals.map((i) => (0, import_pitch_distance.transpose)(tonic, i));
122
+ const notes2 = tonic.empty ? [] : intervals.map((i) => (0, import_pitch_distance.transpose)(tonic.pc, i));
110
123
  typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];
111
- const symbol = `${tonic.empty ? "" : tonic.pc}${typeName}${root.empty || rootDegree <= 1 ? "" : "/" + root.pc}`;
112
- const name = `${optionalTonic ? tonic.pc + " " : ""}${type.name}${rootDegree > 1 && optionalRoot ? " over " + root.pc : ""}`;
124
+ const symbol = `${tonic.empty ? "" : tonic.pc}${typeName}${hasRoot && rootDegree > 1 ? "/" + root.pc : hasBass ? "/" + bass.pc : ""}`;
125
+ const name = `${optionalTonic ? tonic.pc + " " : ""}${type.name}${hasRoot && rootDegree > 1 ? " over " + root.pc : hasBass ? " over " + bass.pc : ""}`;
113
126
  return {
114
127
  ...type,
115
128
  name,
116
129
  symbol,
130
+ tonic: tonic.pc,
117
131
  type: type.name,
118
- root: root.name,
132
+ root: root.pc,
133
+ bass: hasBass ? bass.pc : "",
119
134
  intervals,
120
135
  rootDegree,
121
- tonic: tonic.name,
122
- notes
136
+ notes: notes2
123
137
  };
124
138
  }
125
- var chord = deprecate("Chord.chord", "Chord.get", get);
139
+ var chord = get;
126
140
  function transpose(chordName, interval) {
127
- const [tonic, type] = tokenize(chordName);
141
+ const [tonic, type, bass] = tokenize(chordName);
128
142
  if (!tonic) {
129
143
  return chordName;
130
144
  }
131
- return (0, import_pitch_distance.transpose)(tonic, interval) + type;
145
+ const tr = (0, import_pitch_distance.transpose)(bass, interval);
146
+ const slash = tr ? "/" + tr : "";
147
+ return (0, import_pitch_distance.transpose)(tonic, interval) + type + slash;
132
148
  }
133
149
  function chordScales(name) {
134
150
  const s = get(name);
@@ -145,14 +161,22 @@ function reduced(chordName) {
145
161
  const isSubset = (0, import_pcset.isSubsetOf)(s.chroma);
146
162
  return (0, import_chord_type.all)().filter((chord2) => isSubset(chord2.chroma)).map((chord2) => s.tonic + chord2.aliases[0]);
147
163
  }
148
- function degrees(chordName) {
149
- const { intervals, tonic } = get(chordName);
150
- const transpose2 = (0, import_pitch_distance.tonicIntervalsTransposer)(intervals, tonic);
164
+ function notes(chordName, tonic) {
165
+ const chord2 = get(chordName);
166
+ const note2 = tonic || chord2.tonic;
167
+ if (!note2 || chord2.empty) return [];
168
+ return chord2.intervals.map((ivl) => (0, import_pitch_distance.transpose)(note2, ivl));
169
+ }
170
+ function degrees(chordName, tonic) {
171
+ const chord2 = get(chordName);
172
+ const note2 = tonic || chord2.tonic;
173
+ const transpose2 = (0, import_pitch_distance.tonicIntervalsTransposer)(chord2.intervals, note2);
151
174
  return (degree) => degree ? transpose2(degree > 0 ? degree - 1 : degree) : "";
152
175
  }
153
- function steps(chordName) {
154
- const { intervals, tonic } = get(chordName);
155
- return (0, import_pitch_distance.tonicIntervalsTransposer)(intervals, tonic);
176
+ function steps(chordName, tonic) {
177
+ const chord2 = get(chordName);
178
+ const note2 = tonic || chord2.tonic;
179
+ return (0, import_pitch_distance.tonicIntervalsTransposer)(chord2.intervals, note2);
156
180
  }
157
181
  var chord_default = {
158
182
  getChord,
@@ -165,7 +189,7 @@ var chord_default = {
165
189
  transpose,
166
190
  degrees,
167
191
  steps,
168
- // deprecate
192
+ notes,
169
193
  chord
170
194
  };
171
195
  // Annotate the CommonJS export names for ESM import in node:
@@ -173,11 +197,11 @@ var chord_default = {
173
197
  chord,
174
198
  chordScales,
175
199
  degrees,
176
- deprecate,
177
200
  detect,
178
201
  extended,
179
202
  get,
180
203
  getChord,
204
+ notes,
181
205
  reduced,
182
206
  steps,
183
207
  tokenize,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["import { detect } from \"@tonaljs/chord-detect\";\nimport {\n ChordType,\n all as chordTypes,\n get as getChordType,\n} from \"@tonaljs/chord-type\";\nimport { isSubsetOf, isSupersetOf } from \"@tonaljs/pcset\";\nimport {\n distance,\n tonicIntervalsTransposer,\n transpose as transposeNote,\n} from \"@tonaljs/pitch-distance\";\nimport { NoteName, note, tokenizeNote } from \"@tonaljs/pitch-note\";\nimport { all as scaleTypes } from \"@tonaljs/scale-type\";\n\nexport { detect } from \"@tonaljs/chord-detect\";\n\nexport function deprecate<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ResultFn extends (this: any, ...newArgs: any[]) => ReturnType<ResultFn>,\n>(original: string, alternative: string, fn: ResultFn) {\n return function (this: unknown, ...args: unknown[]): ReturnType<ResultFn> {\n // tslint:disable-next-line\n console.warn(`${original} is deprecated. Use ${alternative}.`);\n return fn.apply(this, args);\n };\n}\n\ntype ChordName = string;\ntype ChordNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Chord extends ChordType {\n tonic: string | null;\n type: string;\n root: string;\n rootDegree: number;\n symbol: string;\n notes: NoteName[];\n}\n\nconst NoChord: Chord = {\n empty: true,\n name: \"\",\n symbol: \"\",\n root: \"\",\n rootDegree: 0,\n type: \"\",\n tonic: null,\n setNum: NaN,\n quality: \"Unknown\",\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n// 6, 64, 7, 9, 11 and 13 are consider part of the chord\n// (see https://github.com/danigb/tonal/issues/55)\n//const NUM_TYPES = /^(6|64|7|9|11|13)$/;\n/**\n * Tokenize a chord name. It returns an array with the tonic and chord type\n * If not tonic is found, all the name is considered the chord name.\n *\n * This function does NOT check if the chord type exists or not. It only tries\n * to split the tonic and chord type.\n *\n * @function\n * @param {string} name - the chord name\n * @return {Array} an array with [tonic, type]\n * @example\n * tokenize(\"Cmaj7\") // => [ \"C\", \"maj7\" ]\n * tokenize(\"C7\") // => [ \"C\", \"7\" ]\n * tokenize(\"mMaj7\") // => [ null, \"mMaj7\" ]\n * tokenize(\"Cnonsense\") // => [ null, \"nonsense\" ]\n */\nexport function tokenize(name: string): ChordNameTokens {\n const [letter, acc, oct, type] = tokenizeNote(name);\n if (letter === \"\") {\n return [\"\", name];\n }\n // aug is augmented (see https://github.com/danigb/tonal/issues/55)\n if (letter === \"A\" && type === \"ug\") {\n return [\"\", \"aug\"];\n }\n return [letter + acc, oct + type];\n}\n\n/**\n * Get a Chord from a chord name.\n */\nexport function get(src: ChordName | ChordNameTokens): Chord {\n if (src === \"\") {\n return NoChord;\n }\n if (Array.isArray(src) && src.length === 2) {\n return getChord(src[1], src[0]);\n } else {\n const [tonic, type] = tokenize(src);\n const chord = getChord(type, tonic);\n return chord.empty ? getChord(src) : chord;\n }\n}\n\n/**\n * Get chord properties\n *\n * @param typeName - the chord type name\n * @param [tonic] - Optional tonic\n * @param [root] - Optional root (requires a tonic)\n */\nexport function getChord(\n typeName: string,\n optionalTonic?: string,\n optionalRoot?: string,\n): Chord {\n const type = getChordType(typeName);\n const tonic = note(optionalTonic || \"\");\n const root = note(optionalRoot || \"\");\n\n if (\n type.empty ||\n (optionalTonic && tonic.empty) ||\n (optionalRoot && root.empty)\n ) {\n return NoChord;\n }\n\n const rootInterval = distance(tonic.pc, root.pc);\n const rootDegree = type.intervals.indexOf(rootInterval) + 1;\n if (!root.empty && !rootDegree) {\n return NoChord;\n }\n\n const intervals = Array.from(type.intervals);\n\n for (let i = 1; i < rootDegree; i++) {\n const num = intervals[0][0];\n const quality = intervals[0][1];\n const newNum = parseInt(num, 10) + 7;\n intervals.push(`${newNum}${quality}`);\n intervals.shift();\n }\n\n const notes = tonic.empty\n ? []\n : intervals.map((i) => transposeNote(tonic, i));\n\n typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];\n const symbol = `${tonic.empty ? \"\" : tonic.pc}${typeName}${\n root.empty || rootDegree <= 1 ? \"\" : \"/\" + root.pc\n }`;\n const name = `${optionalTonic ? tonic.pc + \" \" : \"\"}${type.name}${\n rootDegree > 1 && optionalRoot ? \" over \" + root.pc : \"\"\n }`;\n return {\n ...type,\n name,\n symbol,\n type: type.name,\n root: root.name,\n intervals,\n rootDegree,\n tonic: tonic.name,\n notes,\n };\n}\n\nexport const chord = deprecate(\"Chord.chord\", \"Chord.get\", get);\n\n/**\n * Transpose a chord name\n *\n * @param {string} chordName - the chord name\n * @return {string} the transposed chord\n *\n * @example\n * transpose('Dm7', 'P4') // => 'Gm7\n */\nexport function transpose(chordName: string, interval: string): string {\n const [tonic, type] = tokenize(chordName);\n if (!tonic) {\n return chordName;\n }\n return transposeNote(tonic, interval) + type;\n}\n\n/**\n * Get all scales where the given chord fits\n *\n * @example\n * chordScales('C7b9')\n * // => [\"phrygian dominant\", \"flamenco\", \"spanish heptatonic\", \"half-whole diminished\", \"chromatic\"]\n */\nexport function chordScales(name: string): string[] {\n const s = get(name);\n const isChordIncluded = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isChordIncluded(scale.chroma))\n .map((scale) => scale.name);\n}\n/**\n * Get all chords names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @example\n * extended(\"CMaj7\")\n * // => [ 'Cmaj#4', 'Cmaj7#9#11', 'Cmaj9', 'CM7add13', 'Cmaj13', 'Cmaj9#11', 'CM13#11', 'CM7b9' ]\n */\nexport function extended(chordName: string): string[] {\n const s = get(chordName);\n const isSuperset = isSupersetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSuperset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Find all chords names that are a subset of the given one\n * (has less notes but all from the given chord)\n *\n * @example\n */\nexport function reduced(chordName: string): string[] {\n const s = get(chordName);\n const isSubset = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSubset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3, 4].map(Chord.degrees(\"C\")) => [\"C\", \"E\", \"G\", \"C\"]\n * [1, 2, 3, 4].map(Chord.degrees(\"C4\")) => [\"C4\", \"E4\", \"G4\", \"C5\"]\n */\nexport function degrees(chordName: string | ChordNameTokens) {\n const { intervals, tonic } = get(chordName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(chordName: string | ChordNameTokens) {\n const { intervals, tonic } = get(chordName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n getChord,\n get,\n detect,\n chordScales,\n extended,\n reduced,\n tokenize,\n transpose,\n degrees,\n steps,\n\n // deprecate\n chord,\n};\n"],"mappings":"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","names":["import_chord_detect","chord","getChordType","transposeNote","scaleTypes","chordTypes","transpose"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["import { detect } from \"@tonaljs/chord-detect\";\nimport {\n ChordType,\n all as chordTypes,\n get as getChordType,\n} from \"@tonaljs/chord-type\";\nimport { subtract } from \"@tonaljs/interval\";\nimport { isSubsetOf, isSupersetOf } from \"@tonaljs/pcset\";\nimport {\n distance,\n tonicIntervalsTransposer,\n transpose as transposeNote,\n} from \"@tonaljs/pitch-distance\";\nimport { NoteName, note, tokenizeNote } from \"@tonaljs/pitch-note\";\nimport { all as scaleTypes } from \"@tonaljs/scale-type\";\n\nexport { detect } from \"@tonaljs/chord-detect\";\n\ntype ChordNameOrTokens =\n | string // full name to be parsed\n | [string] // only the name\n | [string, string] // tonic, name\n | [string, string, string]; // tonic, name, bass\ntype ChordNameTokens = [string, string, string]; // [TONIC, SCALE TYPE, BASS]\n\nexport interface Chord extends ChordType {\n tonic: string | null;\n type: string;\n root: string;\n bass: string;\n rootDegree: number;\n symbol: string;\n notes: NoteName[];\n}\n\nconst NoChord: Chord = {\n empty: true,\n name: \"\",\n symbol: \"\",\n root: \"\",\n bass: \"\",\n rootDegree: 0,\n type: \"\",\n tonic: null,\n setNum: NaN,\n quality: \"Unknown\",\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n// 6, 64, 7, 9, 11 and 13 are consider part of the chord\n// (see https://github.com/danigb/tonal/issues/55)\n//const NUM_TYPES = /^(6|64|7|9|11|13)$/;\n/**\n * Tokenize a chord name. It returns an array with the tonic, chord type and bass\n * If not tonic is found, all the name is considered the chord name.\n *\n * This function does NOT check if the chord type exists or not. It only tries\n * to split the tonic and chord type.\n *\n * This function does NOT check if the bass is part of the chord or not but it\n * only accepts a pitch class as bass\n *\n * @function\n * @param {string} name - the chord name\n * @return {Array} an array with [tonic, type, bass]\n * @example\n * tokenize(\"Cmaj7\") // => [ \"C\", \"maj7\" ]\n * tokenize(\"C7\") // => [ \"C\", \"7\" ]\n * tokenize(\"mMaj7\") // => [ null, \"mMaj7\" ]\n * tokenize(\"Cnonsense\") // => [ null, \"nonsense\" ]\n */\nexport function tokenize(name: string): ChordNameTokens {\n const [letter, acc, oct, type] = tokenizeNote(name);\n if (letter === \"\") {\n return tokenizeBass(\"\", name);\n } else if (letter === \"A\" && type === \"ug\") {\n return tokenizeBass(\"\", \"aug\");\n } else {\n return tokenizeBass(letter + acc, oct + type);\n }\n}\n\nfunction tokenizeBass(note: string, chord: string): ChordNameTokens {\n const split = chord.split(\"/\");\n if (split.length === 1) {\n return [note, split[0], \"\"];\n }\n const [letter, acc, oct, type] = tokenizeNote(split[1]);\n // Only a pitch class is accepted as bass note\n if (letter !== \"\" && oct === \"\" && type === \"\") {\n return [note, split[0], letter + acc];\n } else {\n return [note, chord, \"\"];\n }\n}\n\n/**\n * Get a Chord from a chord name.\n */\nexport function get(src: ChordNameOrTokens): Chord {\n if (Array.isArray(src)) {\n return getChord(src[1] || \"\", src[0], src[2]);\n } else if (src === \"\") {\n return NoChord;\n } else {\n const [tonic, type, bass] = tokenize(src);\n const chord = getChord(type, tonic, bass);\n return chord.empty ? getChord(src) : chord;\n }\n}\n\n/**\n * Get chord properties\n *\n * @param typeName - the chord type name\n * @param [tonic] - Optional tonic\n * @param [root] - Optional root (requires a tonic)\n */\nexport function getChord(\n typeName: string,\n optionalTonic?: string,\n optionalBass?: string,\n): Chord {\n const type = getChordType(typeName);\n const tonic = note(optionalTonic || \"\");\n const bass = note(optionalBass || \"\");\n\n if (\n type.empty ||\n (optionalTonic && tonic.empty) ||\n (optionalBass && bass.empty)\n ) {\n return NoChord;\n }\n\n const bassInterval = distance(tonic.pc, bass.pc);\n const bassIndex = type.intervals.indexOf(bassInterval);\n const hasRoot = bassIndex >= 0;\n const root = hasRoot ? bass : note(\"\");\n const rootDegree = bassIndex === -1 ? NaN : bassIndex + 1;\n const hasBass = bass.pc && bass.pc !== tonic.pc;\n\n const intervals = Array.from(type.intervals);\n\n if (hasRoot) {\n for (let i = 1; i < rootDegree; i++) {\n const num = intervals[0][0];\n const quality = intervals[0][1];\n const newNum = parseInt(num, 10) + 7;\n intervals.push(`${newNum}${quality}`);\n intervals.shift();\n }\n } else if (hasBass) {\n const ivl = subtract(distance(tonic.pc, bass.pc), \"8P\");\n if (ivl) intervals.unshift(ivl);\n }\n\n const notes = tonic.empty\n ? []\n : intervals.map((i) => transposeNote(tonic.pc, i));\n\n typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];\n const symbol = `${tonic.empty ? \"\" : tonic.pc}${typeName}${\n hasRoot && rootDegree > 1 ? \"/\" + root.pc : hasBass ? \"/\" + bass.pc : \"\"\n }`;\n const name = `${optionalTonic ? tonic.pc + \" \" : \"\"}${type.name}${\n hasRoot && rootDegree > 1\n ? \" over \" + root.pc\n : hasBass\n ? \" over \" + bass.pc\n : \"\"\n }`;\n return {\n ...type,\n name,\n symbol,\n tonic: tonic.pc,\n type: type.name,\n root: root.pc,\n bass: hasBass ? bass.pc : \"\",\n intervals,\n rootDegree,\n notes,\n };\n}\n\nexport const chord = get;\n\n/**\n * Transpose a chord name\n *\n * @param {string} chordName - the chord name\n * @return {string} the transposed chord\n *\n * @example\n * transpose('Dm7', 'P4') // => 'Gm7\n */\nexport function transpose(chordName: string, interval: string): string {\n const [tonic, type, bass] = tokenize(chordName);\n if (!tonic) {\n return chordName;\n }\n const tr = transposeNote(bass, interval);\n const slash = tr ? \"/\" + tr : \"\";\n return transposeNote(tonic, interval) + type + slash;\n}\n\n/**\n * Get all scales where the given chord fits\n *\n * @example\n * chordScales('C7b9')\n * // => [\"phrygian dominant\", \"flamenco\", \"spanish heptatonic\", \"half-whole diminished\", \"chromatic\"]\n */\nexport function chordScales(name: string): string[] {\n const s = get(name);\n const isChordIncluded = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isChordIncluded(scale.chroma))\n .map((scale) => scale.name);\n}\n/**\n * Get all chords names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @example\n * extended(\"CMaj7\")\n * // => [ 'Cmaj#4', 'Cmaj7#9#11', 'Cmaj9', 'CM7add13', 'Cmaj13', 'Cmaj9#11', 'CM13#11', 'CM7b9' ]\n */\nexport function extended(chordName: string): string[] {\n const s = get(chordName);\n const isSuperset = isSupersetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSuperset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Find all chords names that are a subset of the given one\n * (has less notes but all from the given chord)\n *\n * @example\n */\nexport function reduced(chordName: string): string[] {\n const s = get(chordName);\n const isSubset = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSubset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Return the chord notes\n */\nexport function notes(chordName: ChordNameOrTokens, tonic?: string): string[] {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n if (!note || chord.empty) return [];\n return chord.intervals.map((ivl) => transposeNote(note, ivl));\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3, 4].map(Chord.degrees(\"C\")) => [\"C\", \"E\", \"G\", \"C\"]\n * [1, 2, 3, 4].map(Chord.degrees(\"C4\")) => [\"C4\", \"E4\", \"G4\", \"C5\"]\n */\nexport function degrees(chordName: ChordNameOrTokens, tonic?: string) {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n const transpose = tonicIntervalsTransposer(chord.intervals, note);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(chordName: ChordNameOrTokens, tonic?: string) {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n return tonicIntervalsTransposer(chord.intervals, note);\n}\n\n/** @deprecated */\nexport default {\n getChord,\n get,\n detect,\n chordScales,\n extended,\n reduced,\n tokenize,\n transpose,\n degrees,\n steps,\n notes,\n chord,\n};\n"],"mappings":"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","names":["import_chord_detect","note","chord","getChordType","notes","transposeNote","scaleTypes","chordTypes","transpose"]}
package/dist/index.mjs CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  all as chordTypes,
5
5
  get as getChordType
6
6
  } from "@tonaljs/chord-type";
7
+ import { subtract } from "@tonaljs/interval";
7
8
  import { isSubsetOf, isSupersetOf } from "@tonaljs/pcset";
8
9
  import {
9
10
  distance,
@@ -13,17 +14,12 @@ import {
13
14
  import { note, tokenizeNote } from "@tonaljs/pitch-note";
14
15
  import { all as scaleTypes } from "@tonaljs/scale-type";
15
16
  import { detect as detect2 } from "@tonaljs/chord-detect";
16
- function deprecate(original, alternative, fn) {
17
- return function(...args) {
18
- console.warn(`${original} is deprecated. Use ${alternative}.`);
19
- return fn.apply(this, args);
20
- };
21
- }
22
17
  var NoChord = {
23
18
  empty: true,
24
19
  name: "",
25
20
  symbol: "",
26
21
  root: "",
22
+ bass: "",
27
23
  rootDegree: 0,
28
24
  type: "",
29
25
  tonic: null,
@@ -38,68 +34,88 @@ var NoChord = {
38
34
  function tokenize(name) {
39
35
  const [letter, acc, oct, type] = tokenizeNote(name);
40
36
  if (letter === "") {
41
- return ["", name];
37
+ return tokenizeBass("", name);
38
+ } else if (letter === "A" && type === "ug") {
39
+ return tokenizeBass("", "aug");
40
+ } else {
41
+ return tokenizeBass(letter + acc, oct + type);
42
+ }
43
+ }
44
+ function tokenizeBass(note2, chord2) {
45
+ const split = chord2.split("/");
46
+ if (split.length === 1) {
47
+ return [note2, split[0], ""];
42
48
  }
43
- if (letter === "A" && type === "ug") {
44
- return ["", "aug"];
49
+ const [letter, acc, oct, type] = tokenizeNote(split[1]);
50
+ if (letter !== "" && oct === "" && type === "") {
51
+ return [note2, split[0], letter + acc];
52
+ } else {
53
+ return [note2, chord2, ""];
45
54
  }
46
- return [letter + acc, oct + type];
47
55
  }
48
56
  function get(src) {
49
- if (src === "") {
57
+ if (Array.isArray(src)) {
58
+ return getChord(src[1] || "", src[0], src[2]);
59
+ } else if (src === "") {
50
60
  return NoChord;
51
- }
52
- if (Array.isArray(src) && src.length === 2) {
53
- return getChord(src[1], src[0]);
54
61
  } else {
55
- const [tonic, type] = tokenize(src);
56
- const chord2 = getChord(type, tonic);
62
+ const [tonic, type, bass] = tokenize(src);
63
+ const chord2 = getChord(type, tonic, bass);
57
64
  return chord2.empty ? getChord(src) : chord2;
58
65
  }
59
66
  }
60
- function getChord(typeName, optionalTonic, optionalRoot) {
67
+ function getChord(typeName, optionalTonic, optionalBass) {
61
68
  const type = getChordType(typeName);
62
69
  const tonic = note(optionalTonic || "");
63
- const root = note(optionalRoot || "");
64
- if (type.empty || optionalTonic && tonic.empty || optionalRoot && root.empty) {
65
- return NoChord;
66
- }
67
- const rootInterval = distance(tonic.pc, root.pc);
68
- const rootDegree = type.intervals.indexOf(rootInterval) + 1;
69
- if (!root.empty && !rootDegree) {
70
+ const bass = note(optionalBass || "");
71
+ if (type.empty || optionalTonic && tonic.empty || optionalBass && bass.empty) {
70
72
  return NoChord;
71
73
  }
74
+ const bassInterval = distance(tonic.pc, bass.pc);
75
+ const bassIndex = type.intervals.indexOf(bassInterval);
76
+ const hasRoot = bassIndex >= 0;
77
+ const root = hasRoot ? bass : note("");
78
+ const rootDegree = bassIndex === -1 ? NaN : bassIndex + 1;
79
+ const hasBass = bass.pc && bass.pc !== tonic.pc;
72
80
  const intervals = Array.from(type.intervals);
73
- for (let i = 1; i < rootDegree; i++) {
74
- const num = intervals[0][0];
75
- const quality = intervals[0][1];
76
- const newNum = parseInt(num, 10) + 7;
77
- intervals.push(`${newNum}${quality}`);
78
- intervals.shift();
81
+ if (hasRoot) {
82
+ for (let i = 1; i < rootDegree; i++) {
83
+ const num = intervals[0][0];
84
+ const quality = intervals[0][1];
85
+ const newNum = parseInt(num, 10) + 7;
86
+ intervals.push(`${newNum}${quality}`);
87
+ intervals.shift();
88
+ }
89
+ } else if (hasBass) {
90
+ const ivl = subtract(distance(tonic.pc, bass.pc), "8P");
91
+ if (ivl) intervals.unshift(ivl);
79
92
  }
80
- const notes = tonic.empty ? [] : intervals.map((i) => transposeNote(tonic, i));
93
+ const notes2 = tonic.empty ? [] : intervals.map((i) => transposeNote(tonic.pc, i));
81
94
  typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];
82
- const symbol = `${tonic.empty ? "" : tonic.pc}${typeName}${root.empty || rootDegree <= 1 ? "" : "/" + root.pc}`;
83
- const name = `${optionalTonic ? tonic.pc + " " : ""}${type.name}${rootDegree > 1 && optionalRoot ? " over " + root.pc : ""}`;
95
+ const symbol = `${tonic.empty ? "" : tonic.pc}${typeName}${hasRoot && rootDegree > 1 ? "/" + root.pc : hasBass ? "/" + bass.pc : ""}`;
96
+ const name = `${optionalTonic ? tonic.pc + " " : ""}${type.name}${hasRoot && rootDegree > 1 ? " over " + root.pc : hasBass ? " over " + bass.pc : ""}`;
84
97
  return {
85
98
  ...type,
86
99
  name,
87
100
  symbol,
101
+ tonic: tonic.pc,
88
102
  type: type.name,
89
- root: root.name,
103
+ root: root.pc,
104
+ bass: hasBass ? bass.pc : "",
90
105
  intervals,
91
106
  rootDegree,
92
- tonic: tonic.name,
93
- notes
107
+ notes: notes2
94
108
  };
95
109
  }
96
- var chord = deprecate("Chord.chord", "Chord.get", get);
110
+ var chord = get;
97
111
  function transpose(chordName, interval) {
98
- const [tonic, type] = tokenize(chordName);
112
+ const [tonic, type, bass] = tokenize(chordName);
99
113
  if (!tonic) {
100
114
  return chordName;
101
115
  }
102
- return transposeNote(tonic, interval) + type;
116
+ const tr = transposeNote(bass, interval);
117
+ const slash = tr ? "/" + tr : "";
118
+ return transposeNote(tonic, interval) + type + slash;
103
119
  }
104
120
  function chordScales(name) {
105
121
  const s = get(name);
@@ -116,14 +132,22 @@ function reduced(chordName) {
116
132
  const isSubset = isSubsetOf(s.chroma);
117
133
  return chordTypes().filter((chord2) => isSubset(chord2.chroma)).map((chord2) => s.tonic + chord2.aliases[0]);
118
134
  }
119
- function degrees(chordName) {
120
- const { intervals, tonic } = get(chordName);
121
- const transpose2 = tonicIntervalsTransposer(intervals, tonic);
135
+ function notes(chordName, tonic) {
136
+ const chord2 = get(chordName);
137
+ const note2 = tonic || chord2.tonic;
138
+ if (!note2 || chord2.empty) return [];
139
+ return chord2.intervals.map((ivl) => transposeNote(note2, ivl));
140
+ }
141
+ function degrees(chordName, tonic) {
142
+ const chord2 = get(chordName);
143
+ const note2 = tonic || chord2.tonic;
144
+ const transpose2 = tonicIntervalsTransposer(chord2.intervals, note2);
122
145
  return (degree) => degree ? transpose2(degree > 0 ? degree - 1 : degree) : "";
123
146
  }
124
- function steps(chordName) {
125
- const { intervals, tonic } = get(chordName);
126
- return tonicIntervalsTransposer(intervals, tonic);
147
+ function steps(chordName, tonic) {
148
+ const chord2 = get(chordName);
149
+ const note2 = tonic || chord2.tonic;
150
+ return tonicIntervalsTransposer(chord2.intervals, note2);
127
151
  }
128
152
  var chord_default = {
129
153
  getChord,
@@ -136,7 +160,7 @@ var chord_default = {
136
160
  transpose,
137
161
  degrees,
138
162
  steps,
139
- // deprecate
163
+ notes,
140
164
  chord
141
165
  };
142
166
  export {
@@ -144,11 +168,11 @@ export {
144
168
  chordScales,
145
169
  chord_default as default,
146
170
  degrees,
147
- deprecate,
148
171
  detect2 as detect,
149
172
  extended,
150
173
  get,
151
174
  getChord,
175
+ notes,
152
176
  reduced,
153
177
  steps,
154
178
  tokenize,
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["import { detect } from \"@tonaljs/chord-detect\";\nimport {\n ChordType,\n all as chordTypes,\n get as getChordType,\n} from \"@tonaljs/chord-type\";\nimport { isSubsetOf, isSupersetOf } from \"@tonaljs/pcset\";\nimport {\n distance,\n tonicIntervalsTransposer,\n transpose as transposeNote,\n} from \"@tonaljs/pitch-distance\";\nimport { NoteName, note, tokenizeNote } from \"@tonaljs/pitch-note\";\nimport { all as scaleTypes } from \"@tonaljs/scale-type\";\n\nexport { detect } from \"@tonaljs/chord-detect\";\n\nexport function deprecate<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ResultFn extends (this: any, ...newArgs: any[]) => ReturnType<ResultFn>,\n>(original: string, alternative: string, fn: ResultFn) {\n return function (this: unknown, ...args: unknown[]): ReturnType<ResultFn> {\n // tslint:disable-next-line\n console.warn(`${original} is deprecated. Use ${alternative}.`);\n return fn.apply(this, args);\n };\n}\n\ntype ChordName = string;\ntype ChordNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Chord extends ChordType {\n tonic: string | null;\n type: string;\n root: string;\n rootDegree: number;\n symbol: string;\n notes: NoteName[];\n}\n\nconst NoChord: Chord = {\n empty: true,\n name: \"\",\n symbol: \"\",\n root: \"\",\n rootDegree: 0,\n type: \"\",\n tonic: null,\n setNum: NaN,\n quality: \"Unknown\",\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n// 6, 64, 7, 9, 11 and 13 are consider part of the chord\n// (see https://github.com/danigb/tonal/issues/55)\n//const NUM_TYPES = /^(6|64|7|9|11|13)$/;\n/**\n * Tokenize a chord name. It returns an array with the tonic and chord type\n * If not tonic is found, all the name is considered the chord name.\n *\n * This function does NOT check if the chord type exists or not. It only tries\n * to split the tonic and chord type.\n *\n * @function\n * @param {string} name - the chord name\n * @return {Array} an array with [tonic, type]\n * @example\n * tokenize(\"Cmaj7\") // => [ \"C\", \"maj7\" ]\n * tokenize(\"C7\") // => [ \"C\", \"7\" ]\n * tokenize(\"mMaj7\") // => [ null, \"mMaj7\" ]\n * tokenize(\"Cnonsense\") // => [ null, \"nonsense\" ]\n */\nexport function tokenize(name: string): ChordNameTokens {\n const [letter, acc, oct, type] = tokenizeNote(name);\n if (letter === \"\") {\n return [\"\", name];\n }\n // aug is augmented (see https://github.com/danigb/tonal/issues/55)\n if (letter === \"A\" && type === \"ug\") {\n return [\"\", \"aug\"];\n }\n return [letter + acc, oct + type];\n}\n\n/**\n * Get a Chord from a chord name.\n */\nexport function get(src: ChordName | ChordNameTokens): Chord {\n if (src === \"\") {\n return NoChord;\n }\n if (Array.isArray(src) && src.length === 2) {\n return getChord(src[1], src[0]);\n } else {\n const [tonic, type] = tokenize(src);\n const chord = getChord(type, tonic);\n return chord.empty ? getChord(src) : chord;\n }\n}\n\n/**\n * Get chord properties\n *\n * @param typeName - the chord type name\n * @param [tonic] - Optional tonic\n * @param [root] - Optional root (requires a tonic)\n */\nexport function getChord(\n typeName: string,\n optionalTonic?: string,\n optionalRoot?: string,\n): Chord {\n const type = getChordType(typeName);\n const tonic = note(optionalTonic || \"\");\n const root = note(optionalRoot || \"\");\n\n if (\n type.empty ||\n (optionalTonic && tonic.empty) ||\n (optionalRoot && root.empty)\n ) {\n return NoChord;\n }\n\n const rootInterval = distance(tonic.pc, root.pc);\n const rootDegree = type.intervals.indexOf(rootInterval) + 1;\n if (!root.empty && !rootDegree) {\n return NoChord;\n }\n\n const intervals = Array.from(type.intervals);\n\n for (let i = 1; i < rootDegree; i++) {\n const num = intervals[0][0];\n const quality = intervals[0][1];\n const newNum = parseInt(num, 10) + 7;\n intervals.push(`${newNum}${quality}`);\n intervals.shift();\n }\n\n const notes = tonic.empty\n ? []\n : intervals.map((i) => transposeNote(tonic, i));\n\n typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];\n const symbol = `${tonic.empty ? \"\" : tonic.pc}${typeName}${\n root.empty || rootDegree <= 1 ? \"\" : \"/\" + root.pc\n }`;\n const name = `${optionalTonic ? tonic.pc + \" \" : \"\"}${type.name}${\n rootDegree > 1 && optionalRoot ? \" over \" + root.pc : \"\"\n }`;\n return {\n ...type,\n name,\n symbol,\n type: type.name,\n root: root.name,\n intervals,\n rootDegree,\n tonic: tonic.name,\n notes,\n };\n}\n\nexport const chord = deprecate(\"Chord.chord\", \"Chord.get\", get);\n\n/**\n * Transpose a chord name\n *\n * @param {string} chordName - the chord name\n * @return {string} the transposed chord\n *\n * @example\n * transpose('Dm7', 'P4') // => 'Gm7\n */\nexport function transpose(chordName: string, interval: string): string {\n const [tonic, type] = tokenize(chordName);\n if (!tonic) {\n return chordName;\n }\n return transposeNote(tonic, interval) + type;\n}\n\n/**\n * Get all scales where the given chord fits\n *\n * @example\n * chordScales('C7b9')\n * // => [\"phrygian dominant\", \"flamenco\", \"spanish heptatonic\", \"half-whole diminished\", \"chromatic\"]\n */\nexport function chordScales(name: string): string[] {\n const s = get(name);\n const isChordIncluded = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isChordIncluded(scale.chroma))\n .map((scale) => scale.name);\n}\n/**\n * Get all chords names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @example\n * extended(\"CMaj7\")\n * // => [ 'Cmaj#4', 'Cmaj7#9#11', 'Cmaj9', 'CM7add13', 'Cmaj13', 'Cmaj9#11', 'CM13#11', 'CM7b9' ]\n */\nexport function extended(chordName: string): string[] {\n const s = get(chordName);\n const isSuperset = isSupersetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSuperset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Find all chords names that are a subset of the given one\n * (has less notes but all from the given chord)\n *\n * @example\n */\nexport function reduced(chordName: string): string[] {\n const s = get(chordName);\n const isSubset = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSubset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3, 4].map(Chord.degrees(\"C\")) => [\"C\", \"E\", \"G\", \"C\"]\n * [1, 2, 3, 4].map(Chord.degrees(\"C4\")) => [\"C4\", \"E4\", \"G4\", \"C5\"]\n */\nexport function degrees(chordName: string | ChordNameTokens) {\n const { intervals, tonic } = get(chordName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(chordName: string | ChordNameTokens) {\n const { intervals, tonic } = get(chordName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n getChord,\n get,\n detect,\n chordScales,\n extended,\n reduced,\n tokenize,\n transpose,\n degrees,\n steps,\n\n // deprecate\n chord,\n};\n"],"mappings":"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","names":["detect","chord","transpose"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["import { detect } from \"@tonaljs/chord-detect\";\nimport {\n ChordType,\n all as chordTypes,\n get as getChordType,\n} from \"@tonaljs/chord-type\";\nimport { subtract } from \"@tonaljs/interval\";\nimport { isSubsetOf, isSupersetOf } from \"@tonaljs/pcset\";\nimport {\n distance,\n tonicIntervalsTransposer,\n transpose as transposeNote,\n} from \"@tonaljs/pitch-distance\";\nimport { NoteName, note, tokenizeNote } from \"@tonaljs/pitch-note\";\nimport { all as scaleTypes } from \"@tonaljs/scale-type\";\n\nexport { detect } from \"@tonaljs/chord-detect\";\n\ntype ChordNameOrTokens =\n | string // full name to be parsed\n | [string] // only the name\n | [string, string] // tonic, name\n | [string, string, string]; // tonic, name, bass\ntype ChordNameTokens = [string, string, string]; // [TONIC, SCALE TYPE, BASS]\n\nexport interface Chord extends ChordType {\n tonic: string | null;\n type: string;\n root: string;\n bass: string;\n rootDegree: number;\n symbol: string;\n notes: NoteName[];\n}\n\nconst NoChord: Chord = {\n empty: true,\n name: \"\",\n symbol: \"\",\n root: \"\",\n bass: \"\",\n rootDegree: 0,\n type: \"\",\n tonic: null,\n setNum: NaN,\n quality: \"Unknown\",\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n// 6, 64, 7, 9, 11 and 13 are consider part of the chord\n// (see https://github.com/danigb/tonal/issues/55)\n//const NUM_TYPES = /^(6|64|7|9|11|13)$/;\n/**\n * Tokenize a chord name. It returns an array with the tonic, chord type and bass\n * If not tonic is found, all the name is considered the chord name.\n *\n * This function does NOT check if the chord type exists or not. It only tries\n * to split the tonic and chord type.\n *\n * This function does NOT check if the bass is part of the chord or not but it\n * only accepts a pitch class as bass\n *\n * @function\n * @param {string} name - the chord name\n * @return {Array} an array with [tonic, type, bass]\n * @example\n * tokenize(\"Cmaj7\") // => [ \"C\", \"maj7\" ]\n * tokenize(\"C7\") // => [ \"C\", \"7\" ]\n * tokenize(\"mMaj7\") // => [ null, \"mMaj7\" ]\n * tokenize(\"Cnonsense\") // => [ null, \"nonsense\" ]\n */\nexport function tokenize(name: string): ChordNameTokens {\n const [letter, acc, oct, type] = tokenizeNote(name);\n if (letter === \"\") {\n return tokenizeBass(\"\", name);\n } else if (letter === \"A\" && type === \"ug\") {\n return tokenizeBass(\"\", \"aug\");\n } else {\n return tokenizeBass(letter + acc, oct + type);\n }\n}\n\nfunction tokenizeBass(note: string, chord: string): ChordNameTokens {\n const split = chord.split(\"/\");\n if (split.length === 1) {\n return [note, split[0], \"\"];\n }\n const [letter, acc, oct, type] = tokenizeNote(split[1]);\n // Only a pitch class is accepted as bass note\n if (letter !== \"\" && oct === \"\" && type === \"\") {\n return [note, split[0], letter + acc];\n } else {\n return [note, chord, \"\"];\n }\n}\n\n/**\n * Get a Chord from a chord name.\n */\nexport function get(src: ChordNameOrTokens): Chord {\n if (Array.isArray(src)) {\n return getChord(src[1] || \"\", src[0], src[2]);\n } else if (src === \"\") {\n return NoChord;\n } else {\n const [tonic, type, bass] = tokenize(src);\n const chord = getChord(type, tonic, bass);\n return chord.empty ? getChord(src) : chord;\n }\n}\n\n/**\n * Get chord properties\n *\n * @param typeName - the chord type name\n * @param [tonic] - Optional tonic\n * @param [root] - Optional root (requires a tonic)\n */\nexport function getChord(\n typeName: string,\n optionalTonic?: string,\n optionalBass?: string,\n): Chord {\n const type = getChordType(typeName);\n const tonic = note(optionalTonic || \"\");\n const bass = note(optionalBass || \"\");\n\n if (\n type.empty ||\n (optionalTonic && tonic.empty) ||\n (optionalBass && bass.empty)\n ) {\n return NoChord;\n }\n\n const bassInterval = distance(tonic.pc, bass.pc);\n const bassIndex = type.intervals.indexOf(bassInterval);\n const hasRoot = bassIndex >= 0;\n const root = hasRoot ? bass : note(\"\");\n const rootDegree = bassIndex === -1 ? NaN : bassIndex + 1;\n const hasBass = bass.pc && bass.pc !== tonic.pc;\n\n const intervals = Array.from(type.intervals);\n\n if (hasRoot) {\n for (let i = 1; i < rootDegree; i++) {\n const num = intervals[0][0];\n const quality = intervals[0][1];\n const newNum = parseInt(num, 10) + 7;\n intervals.push(`${newNum}${quality}`);\n intervals.shift();\n }\n } else if (hasBass) {\n const ivl = subtract(distance(tonic.pc, bass.pc), \"8P\");\n if (ivl) intervals.unshift(ivl);\n }\n\n const notes = tonic.empty\n ? []\n : intervals.map((i) => transposeNote(tonic.pc, i));\n\n typeName = type.aliases.indexOf(typeName) !== -1 ? typeName : type.aliases[0];\n const symbol = `${tonic.empty ? \"\" : tonic.pc}${typeName}${\n hasRoot && rootDegree > 1 ? \"/\" + root.pc : hasBass ? \"/\" + bass.pc : \"\"\n }`;\n const name = `${optionalTonic ? tonic.pc + \" \" : \"\"}${type.name}${\n hasRoot && rootDegree > 1\n ? \" over \" + root.pc\n : hasBass\n ? \" over \" + bass.pc\n : \"\"\n }`;\n return {\n ...type,\n name,\n symbol,\n tonic: tonic.pc,\n type: type.name,\n root: root.pc,\n bass: hasBass ? bass.pc : \"\",\n intervals,\n rootDegree,\n notes,\n };\n}\n\nexport const chord = get;\n\n/**\n * Transpose a chord name\n *\n * @param {string} chordName - the chord name\n * @return {string} the transposed chord\n *\n * @example\n * transpose('Dm7', 'P4') // => 'Gm7\n */\nexport function transpose(chordName: string, interval: string): string {\n const [tonic, type, bass] = tokenize(chordName);\n if (!tonic) {\n return chordName;\n }\n const tr = transposeNote(bass, interval);\n const slash = tr ? \"/\" + tr : \"\";\n return transposeNote(tonic, interval) + type + slash;\n}\n\n/**\n * Get all scales where the given chord fits\n *\n * @example\n * chordScales('C7b9')\n * // => [\"phrygian dominant\", \"flamenco\", \"spanish heptatonic\", \"half-whole diminished\", \"chromatic\"]\n */\nexport function chordScales(name: string): string[] {\n const s = get(name);\n const isChordIncluded = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isChordIncluded(scale.chroma))\n .map((scale) => scale.name);\n}\n/**\n * Get all chords names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @example\n * extended(\"CMaj7\")\n * // => [ 'Cmaj#4', 'Cmaj7#9#11', 'Cmaj9', 'CM7add13', 'Cmaj13', 'Cmaj9#11', 'CM13#11', 'CM7b9' ]\n */\nexport function extended(chordName: string): string[] {\n const s = get(chordName);\n const isSuperset = isSupersetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSuperset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Find all chords names that are a subset of the given one\n * (has less notes but all from the given chord)\n *\n * @example\n */\nexport function reduced(chordName: string): string[] {\n const s = get(chordName);\n const isSubset = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => isSubset(chord.chroma))\n .map((chord) => s.tonic + chord.aliases[0]);\n}\n\n/**\n * Return the chord notes\n */\nexport function notes(chordName: ChordNameOrTokens, tonic?: string): string[] {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n if (!note || chord.empty) return [];\n return chord.intervals.map((ivl) => transposeNote(note, ivl));\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3, 4].map(Chord.degrees(\"C\")) => [\"C\", \"E\", \"G\", \"C\"]\n * [1, 2, 3, 4].map(Chord.degrees(\"C4\")) => [\"C4\", \"E4\", \"G4\", \"C5\"]\n */\nexport function degrees(chordName: ChordNameOrTokens, tonic?: string) {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n const transpose = tonicIntervalsTransposer(chord.intervals, note);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(chordName: ChordNameOrTokens, tonic?: string) {\n const chord = get(chordName);\n const note = tonic || chord.tonic;\n return tonicIntervalsTransposer(chord.intervals, note);\n}\n\n/** @deprecated */\nexport default {\n getChord,\n get,\n detect,\n chordScales,\n extended,\n reduced,\n tokenize,\n transpose,\n degrees,\n steps,\n notes,\n chord,\n};\n"],"mappings":"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","names":["detect","note","chord","notes","transpose"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonaljs/chord",
3
- "version": "5.0.3",
3
+ "version": "6.1.0",
4
4
  "description": "Musical chords and its relations",
5
5
  "keywords": [
6
6
  "chord",
@@ -16,13 +16,14 @@
16
16
  ],
17
17
  "types": "dist/index.d.ts",
18
18
  "dependencies": {
19
- "@tonaljs/chord-detect": "4.8.4",
20
- "@tonaljs/chord-type": "5.0.4",
21
- "@tonaljs/collection": "4.8.1",
22
- "@tonaljs/pitch-note": "5.0.3",
23
- "@tonaljs/pitch-distance": "5.0.2",
24
- "@tonaljs/pcset": "4.9.1",
25
- "@tonaljs/scale-type": "4.8.4"
19
+ "@tonaljs/chord-detect": "4.9.0",
20
+ "@tonaljs/chord-type": "5.1.0",
21
+ "@tonaljs/collection": "4.9.0",
22
+ "@tonaljs/interval": "^5.1.0",
23
+ "@tonaljs/pcset": "4.10.0",
24
+ "@tonaljs/pitch-distance": "5.0.4",
25
+ "@tonaljs/pitch-note": "6.0.0",
26
+ "@tonaljs/scale-type": "4.9.0"
26
27
  },
27
28
  "author": "danigb@gmail.com",
28
29
  "license": "MIT",