@tonaljs/scale 4.6.4 → 4.6.10

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/dist/index.d.ts CHANGED
@@ -1,112 +1,114 @@
1
- import { NoteName } from "@tonaljs/core";
2
- import { names as scaleTypeNames, ScaleType } from "@tonaljs/scale-type";
3
- declare type ScaleName = string;
4
- declare type ScaleNameTokens = [string, string];
5
- export interface Scale extends ScaleType {
6
- tonic: string | null;
7
- type: string;
8
- notes: NoteName[];
9
- }
10
- /**
11
- * Given a string with a scale name and (optionally) a tonic, split
12
- * that components.
13
- *
14
- * It retuns an array with the form [ name, tonic ] where tonic can be a
15
- * note name or null and name can be any arbitrary string
16
- * (this function doesn"t check if that scale name exists)
17
- *
18
- * @function
19
- * @param {string} name - the scale name
20
- * @return {Array} an array [tonic, name]
21
- * @example
22
- * tokenize("C mixolydean") // => ["C", "mixolydean"]
23
- * tokenize("anything is valid") // => ["", "anything is valid"]
24
- * tokenize() // => ["", ""]
25
- */
26
- export declare function tokenize(name: ScaleName): ScaleNameTokens;
27
- /**
28
- * Get all scale names
29
- * @function
30
- */
31
- export declare const names: typeof scaleTypeNames;
32
- /**
33
- * Get a Scale from a scale name.
34
- */
35
- export declare function get(src: ScaleName | ScaleNameTokens): Scale;
36
- export declare const scale: (this: unknown, ...args: unknown[]) => Scale;
37
- /**
38
- * Get all chords that fits a given scale
39
- *
40
- * @function
41
- * @param {string} name - the scale name
42
- * @return {Array<string>} - the chord names
43
- *
44
- * @example
45
- * scaleChords("pentatonic") // => ["5", "64", "M", "M6", "Madd9", "Msus2"]
46
- */
47
- export declare function scaleChords(name: string): string[];
48
- /**
49
- * Get all scales names that are a superset of the given one
50
- * (has the same notes and at least one more)
51
- *
52
- * @function
53
- * @param {string} name
54
- * @return {Array} a list of scale names
55
- * @example
56
- * extended("major") // => ["bebop", "bebop dominant", "bebop major", "chromatic", "ichikosucho"]
57
- */
58
- export declare function extended(name: string): string[];
59
- /**
60
- * Find all scales names that are a subset of the given one
61
- * (has less notes but all from the given scale)
62
- *
63
- * @function
64
- * @param {string} name
65
- * @return {Array} a list of scale names
66
- *
67
- * @example
68
- * reduced("major") // => ["ionian pentatonic", "major pentatonic", "ritusen"]
69
- */
70
- export declare function reduced(name: string): string[];
71
- /**
72
- * Given an array of notes, return the scale: a pitch class set starting from
73
- * the first note of the array
74
- *
75
- * @function
76
- * @param {string[]} notes
77
- * @return {string[]} pitch classes with same tonic
78
- * @example
79
- * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => ["C"]
80
- * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => ["D", "F#", "A", "C#"]
81
- */
82
- export declare function scaleNotes(notes: NoteName[]): string[];
83
- declare type ScaleMode = [string, string];
84
- /**
85
- * Find mode names of a scale
86
- *
87
- * @function
88
- * @param {string} name - scale name
89
- * @example
90
- * modeNames("C pentatonic") // => [
91
- * ["C", "major pentatonic"],
92
- * ["D", "egyptian"],
93
- * ["E", "malkos raga"],
94
- * ["G", "ritusen"],
95
- * ["A", "minor pentatonic"]
96
- * ]
97
- */
98
- export declare function modeNames(name: string): ScaleMode[];
99
- export declare function rangeOf(scale: string | string[]): (fromNote: string, toNote: string) => (string | undefined)[];
100
- declare const _default: {
101
- get: typeof get;
102
- names: typeof scaleTypeNames;
103
- extended: typeof extended;
104
- modeNames: typeof modeNames;
105
- reduced: typeof reduced;
106
- scaleChords: typeof scaleChords;
107
- scaleNotes: typeof scaleNotes;
108
- tokenize: typeof tokenize;
109
- rangeOf: typeof rangeOf;
110
- scale: (this: unknown, ...args: unknown[]) => Scale;
111
- };
112
- export default _default;
1
+ import { NoteName } from '@tonaljs/core';
2
+ import { ScaleType, names as names$1 } from '@tonaljs/scale-type';
3
+
4
+ type ScaleName = string;
5
+ type ScaleNameTokens = [string, string];
6
+ interface Scale extends ScaleType {
7
+ tonic: string | null;
8
+ type: string;
9
+ notes: NoteName[];
10
+ }
11
+ /**
12
+ * Given a string with a scale name and (optionally) a tonic, split
13
+ * that components.
14
+ *
15
+ * It retuns an array with the form [ name, tonic ] where tonic can be a
16
+ * note name or null and name can be any arbitrary string
17
+ * (this function doesn"t check if that scale name exists)
18
+ *
19
+ * @function
20
+ * @param {string} name - the scale name
21
+ * @return {Array} an array [tonic, name]
22
+ * @example
23
+ * tokenize("C mixolydean") // => ["C", "mixolydean"]
24
+ * tokenize("anything is valid") // => ["", "anything is valid"]
25
+ * tokenize() // => ["", ""]
26
+ */
27
+ declare function tokenize(name: ScaleName): ScaleNameTokens;
28
+ /**
29
+ * Get all scale names
30
+ * @function
31
+ */
32
+ declare const names: typeof names$1;
33
+ /**
34
+ * Get a Scale from a scale name.
35
+ */
36
+ declare function get(src: ScaleName | ScaleNameTokens): Scale;
37
+ declare const scale: (this: unknown, ...args: unknown[]) => Scale;
38
+ /**
39
+ * Get all chords that fits a given scale
40
+ *
41
+ * @function
42
+ * @param {string} name - the scale name
43
+ * @return {Array<string>} - the chord names
44
+ *
45
+ * @example
46
+ * scaleChords("pentatonic") // => ["5", "64", "M", "M6", "Madd9", "Msus2"]
47
+ */
48
+ declare function scaleChords(name: string): string[];
49
+ /**
50
+ * Get all scales names that are a superset of the given one
51
+ * (has the same notes and at least one more)
52
+ *
53
+ * @function
54
+ * @param {string} name
55
+ * @return {Array} a list of scale names
56
+ * @example
57
+ * extended("major") // => ["bebop", "bebop dominant", "bebop major", "chromatic", "ichikosucho"]
58
+ */
59
+ declare function extended(name: string): string[];
60
+ /**
61
+ * Find all scales names that are a subset of the given one
62
+ * (has less notes but all from the given scale)
63
+ *
64
+ * @function
65
+ * @param {string} name
66
+ * @return {Array} a list of scale names
67
+ *
68
+ * @example
69
+ * reduced("major") // => ["ionian pentatonic", "major pentatonic", "ritusen"]
70
+ */
71
+ declare function reduced(name: string): string[];
72
+ /**
73
+ * Given an array of notes, return the scale: a pitch class set starting from
74
+ * the first note of the array
75
+ *
76
+ * @function
77
+ * @param {string[]} notes
78
+ * @return {string[]} pitch classes with same tonic
79
+ * @example
80
+ * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => ["C"]
81
+ * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => ["D", "F#", "A", "C#"]
82
+ */
83
+ declare function scaleNotes(notes: NoteName[]): string[];
84
+ type ScaleMode = [string, string];
85
+ /**
86
+ * Find mode names of a scale
87
+ *
88
+ * @function
89
+ * @param {string} name - scale name
90
+ * @example
91
+ * modeNames("C pentatonic") // => [
92
+ * ["C", "major pentatonic"],
93
+ * ["D", "egyptian"],
94
+ * ["E", "malkos raga"],
95
+ * ["G", "ritusen"],
96
+ * ["A", "minor pentatonic"]
97
+ * ]
98
+ */
99
+ declare function modeNames(name: string): ScaleMode[];
100
+ declare function rangeOf(scale: string | string[]): (fromNote: string, toNote: string) => (string | undefined)[];
101
+ declare const _default: {
102
+ get: typeof get;
103
+ names: typeof names$1;
104
+ extended: typeof extended;
105
+ modeNames: typeof modeNames;
106
+ reduced: typeof reduced;
107
+ scaleChords: typeof scaleChords;
108
+ scaleNotes: typeof scaleNotes;
109
+ tokenize: typeof tokenize;
110
+ rangeOf: typeof rangeOf;
111
+ scale: (this: unknown, ...args: unknown[]) => Scale;
112
+ };
113
+
114
+ export { Scale, _default as default, extended, get, modeNames, names, rangeOf, reduced, scale, scaleChords, scaleNotes, tokenize };
package/dist/index.js CHANGED
@@ -1,250 +1,162 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tonaljs/chord-type'), require('@tonaljs/collection'), require('@tonaljs/core'), require('@tonaljs/note'), require('@tonaljs/pcset'), require('@tonaljs/scale-type')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@tonaljs/chord-type', '@tonaljs/collection', '@tonaljs/core', '@tonaljs/note', '@tonaljs/pcset', '@tonaljs/scale-type'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Scale = {}, global.chordType, global.collection, global.core, global.note, global.pcset, global.scaleType));
5
- }(this, (function (exports, chordType, collection, core, note, pcset, scaleType) { 'use strict';
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
6
19
 
7
- /*! *****************************************************************************
8
- Copyright (c) Microsoft Corporation.
9
-
10
- Permission to use, copy, modify, and/or distribute this software for any
11
- purpose with or without fee is hereby granted.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
- PERFORMANCE OF THIS SOFTWARE.
20
- ***************************************************************************** */
21
-
22
- var __assign = function() {
23
- __assign = Object.assign || function __assign(t) {
24
- for (var s, i = 1, n = arguments.length; i < n; i++) {
25
- s = arguments[i];
26
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
27
- }
28
- return t;
29
- };
30
- return __assign.apply(this, arguments);
31
- };
32
-
33
- var NoScale = {
34
- empty: true,
35
- name: "",
36
- type: "",
37
- tonic: null,
38
- setNum: NaN,
39
- chroma: "",
40
- normalized: "",
41
- aliases: [],
42
- notes: [],
43
- intervals: [],
44
- };
45
- /**
46
- * Given a string with a scale name and (optionally) a tonic, split
47
- * that components.
48
- *
49
- * It retuns an array with the form [ name, tonic ] where tonic can be a
50
- * note name or null and name can be any arbitrary string
51
- * (this function doesn"t check if that scale name exists)
52
- *
53
- * @function
54
- * @param {string} name - the scale name
55
- * @return {Array} an array [tonic, name]
56
- * @example
57
- * tokenize("C mixolydean") // => ["C", "mixolydean"]
58
- * tokenize("anything is valid") // => ["", "anything is valid"]
59
- * tokenize() // => ["", ""]
60
- */
61
- function tokenize(name) {
62
- if (typeof name !== "string") {
63
- return ["", ""];
64
- }
65
- var i = name.indexOf(" ");
66
- var tonic = core.note(name.substring(0, i));
67
- if (tonic.empty) {
68
- var n = core.note(name);
69
- return n.empty ? ["", name] : [n.name, ""];
70
- }
71
- var type = name.substring(tonic.name.length + 1);
72
- return [tonic.name, type.length ? type : ""];
73
- }
74
- /**
75
- * Get all scale names
76
- * @function
77
- */
78
- var names = scaleType.names;
79
- /**
80
- * Get a Scale from a scale name.
81
- */
82
- function get(src) {
83
- var tokens = Array.isArray(src) ? src : tokenize(src);
84
- var tonic = core.note(tokens[0]).name;
85
- var st = scaleType.get(tokens[1]);
86
- if (st.empty) {
87
- return NoScale;
88
- }
89
- var type = st.name;
90
- var notes = tonic
91
- ? st.intervals.map(function (i) { return core.transpose(tonic, i); })
92
- : [];
93
- var name = tonic ? tonic + " " + type : type;
94
- return __assign(__assign({}, st), { name: name, type: type, tonic: tonic, notes: notes });
95
- }
96
- var scale = core.deprecate("Scale.scale", "Scale.get", get);
97
- /**
98
- * Get all chords that fits a given scale
99
- *
100
- * @function
101
- * @param {string} name - the scale name
102
- * @return {Array<string>} - the chord names
103
- *
104
- * @example
105
- * scaleChords("pentatonic") // => ["5", "64", "M", "M6", "Madd9", "Msus2"]
106
- */
107
- function scaleChords(name) {
108
- var s = get(name);
109
- var inScale = pcset.isSubsetOf(s.chroma);
110
- return chordType.all()
111
- .filter(function (chord) { return inScale(chord.chroma); })
112
- .map(function (chord) { return chord.aliases[0]; });
113
- }
114
- /**
115
- * Get all scales names that are a superset of the given one
116
- * (has the same notes and at least one more)
117
- *
118
- * @function
119
- * @param {string} name
120
- * @return {Array} a list of scale names
121
- * @example
122
- * extended("major") // => ["bebop", "bebop dominant", "bebop major", "chromatic", "ichikosucho"]
123
- */
124
- function extended(name) {
125
- var s = get(name);
126
- var isSuperset = pcset.isSupersetOf(s.chroma);
127
- return scaleType.all()
128
- .filter(function (scale) { return isSuperset(scale.chroma); })
129
- .map(function (scale) { return scale.name; });
130
- }
131
- /**
132
- * Find all scales names that are a subset of the given one
133
- * (has less notes but all from the given scale)
134
- *
135
- * @function
136
- * @param {string} name
137
- * @return {Array} a list of scale names
138
- *
139
- * @example
140
- * reduced("major") // => ["ionian pentatonic", "major pentatonic", "ritusen"]
141
- */
142
- function reduced(name) {
143
- var isSubset = pcset.isSubsetOf(get(name).chroma);
144
- return scaleType.all()
145
- .filter(function (scale) { return isSubset(scale.chroma); })
146
- .map(function (scale) { return scale.name; });
147
- }
148
- /**
149
- * Given an array of notes, return the scale: a pitch class set starting from
150
- * the first note of the array
151
- *
152
- * @function
153
- * @param {string[]} notes
154
- * @return {string[]} pitch classes with same tonic
155
- * @example
156
- * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => ["C"]
157
- * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => ["D", "F#", "A", "C#"]
158
- */
159
- function scaleNotes(notes) {
160
- var pcset = notes.map(function (n) { return core.note(n).pc; }).filter(function (x) { return x; });
161
- var tonic = pcset[0];
162
- var scale = note.sortedUniqNames(pcset);
163
- return collection.rotate(scale.indexOf(tonic), scale);
164
- }
165
- /**
166
- * Find mode names of a scale
167
- *
168
- * @function
169
- * @param {string} name - scale name
170
- * @example
171
- * modeNames("C pentatonic") // => [
172
- * ["C", "major pentatonic"],
173
- * ["D", "egyptian"],
174
- * ["E", "malkos raga"],
175
- * ["G", "ritusen"],
176
- * ["A", "minor pentatonic"]
177
- * ]
178
- */
179
- function modeNames(name) {
180
- var s = get(name);
181
- if (s.empty) {
182
- return [];
183
- }
184
- var tonics = s.tonic ? s.notes : s.intervals;
185
- return pcset.modes(s.chroma)
186
- .map(function (chroma, i) {
187
- var modeName = get(chroma).name;
188
- return modeName ? [tonics[i], modeName] : ["", ""];
189
- })
190
- .filter(function (x) { return x[0]; });
191
- }
192
- function getNoteNameOf(scale) {
193
- var names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;
194
- var chromas = names.map(function (name) { return core.note(name).chroma; });
195
- return function (noteOrMidi) {
196
- var currNote = typeof noteOrMidi === "number"
197
- ? core.note(note.fromMidi(noteOrMidi))
198
- : core.note(noteOrMidi);
199
- var height = currNote.height;
200
- if (height === undefined)
201
- return undefined;
202
- var chroma = height % 12;
203
- var position = chromas.indexOf(chroma);
204
- if (position === -1)
205
- return undefined;
206
- return note.enharmonic(currNote.name, names[position]);
207
- };
208
- }
209
- function rangeOf(scale) {
210
- var getName = getNoteNameOf(scale);
211
- return function (fromNote, toNote) {
212
- var from = core.note(fromNote).height;
213
- var to = core.note(toNote).height;
214
- if (from === undefined || to === undefined)
215
- return [];
216
- return collection.range(from, to)
217
- .map(getName)
218
- .filter(function (x) { return x; });
219
- };
220
- }
221
- var index = {
222
- get: get,
223
- names: names,
224
- extended: extended,
225
- modeNames: modeNames,
226
- reduced: reduced,
227
- scaleChords: scaleChords,
228
- scaleNotes: scaleNotes,
229
- tokenize: tokenize,
230
- rangeOf: rangeOf,
231
- // deprecated
232
- scale: scale,
233
- };
234
-
235
- exports['default'] = index;
236
- exports.extended = extended;
237
- exports.get = get;
238
- exports.modeNames = modeNames;
239
- exports.names = names;
240
- exports.rangeOf = rangeOf;
241
- exports.reduced = reduced;
242
- exports.scale = scale;
243
- exports.scaleChords = scaleChords;
244
- exports.scaleNotes = scaleNotes;
245
- exports.tokenize = tokenize;
246
-
247
- Object.defineProperty(exports, '__esModule', { value: true });
248
-
249
- })));
250
- //# sourceMappingURL=index.js.map
20
+ // index.ts
21
+ var scale_exports = {};
22
+ __export(scale_exports, {
23
+ default: () => scale_default,
24
+ extended: () => extended,
25
+ get: () => get,
26
+ modeNames: () => modeNames,
27
+ names: () => names,
28
+ rangeOf: () => rangeOf,
29
+ reduced: () => reduced,
30
+ scale: () => scale,
31
+ scaleChords: () => scaleChords,
32
+ scaleNotes: () => scaleNotes,
33
+ tokenize: () => tokenize
34
+ });
35
+ module.exports = __toCommonJS(scale_exports);
36
+ var import_chord_type = require("@tonaljs/chord-type");
37
+ var import_collection = require("@tonaljs/collection");
38
+ var import_core = require("@tonaljs/core");
39
+ var import_note = require("@tonaljs/note");
40
+ var import_pcset = require("@tonaljs/pcset");
41
+ var import_scale_type = require("@tonaljs/scale-type");
42
+ var NoScale = {
43
+ empty: true,
44
+ name: "",
45
+ type: "",
46
+ tonic: null,
47
+ setNum: NaN,
48
+ chroma: "",
49
+ normalized: "",
50
+ aliases: [],
51
+ notes: [],
52
+ intervals: []
53
+ };
54
+ function tokenize(name) {
55
+ if (typeof name !== "string") {
56
+ return ["", ""];
57
+ }
58
+ const i = name.indexOf(" ");
59
+ const tonic = (0, import_core.note)(name.substring(0, i));
60
+ if (tonic.empty) {
61
+ const n = (0, import_core.note)(name);
62
+ return n.empty ? ["", name] : [n.name, ""];
63
+ }
64
+ const type = name.substring(tonic.name.length + 1);
65
+ return [tonic.name, type.length ? type : ""];
66
+ }
67
+ var names = import_scale_type.names;
68
+ function get(src) {
69
+ const tokens = Array.isArray(src) ? src : tokenize(src);
70
+ const tonic = (0, import_core.note)(tokens[0]).name;
71
+ const st = (0, import_scale_type.get)(tokens[1]);
72
+ if (st.empty) {
73
+ return NoScale;
74
+ }
75
+ const type = st.name;
76
+ const notes = tonic ? st.intervals.map((i) => (0, import_core.transpose)(tonic, i)) : [];
77
+ const name = tonic ? tonic + " " + type : type;
78
+ return { ...st, name, type, tonic, notes };
79
+ }
80
+ var scale = (0, import_core.deprecate)("Scale.scale", "Scale.get", get);
81
+ function scaleChords(name) {
82
+ const s = get(name);
83
+ const inScale = (0, import_pcset.isSubsetOf)(s.chroma);
84
+ return (0, import_chord_type.all)().filter((chord) => inScale(chord.chroma)).map((chord) => chord.aliases[0]);
85
+ }
86
+ function extended(name) {
87
+ const s = get(name);
88
+ const isSuperset = (0, import_pcset.isSupersetOf)(s.chroma);
89
+ return (0, import_scale_type.all)().filter((scale2) => isSuperset(scale2.chroma)).map((scale2) => scale2.name);
90
+ }
91
+ function reduced(name) {
92
+ const isSubset = (0, import_pcset.isSubsetOf)(get(name).chroma);
93
+ return (0, import_scale_type.all)().filter((scale2) => isSubset(scale2.chroma)).map((scale2) => scale2.name);
94
+ }
95
+ function scaleNotes(notes) {
96
+ const pcset = notes.map((n) => (0, import_core.note)(n).pc).filter((x) => x);
97
+ const tonic = pcset[0];
98
+ const scale2 = (0, import_note.sortedUniqNames)(pcset);
99
+ return (0, import_collection.rotate)(scale2.indexOf(tonic), scale2);
100
+ }
101
+ function modeNames(name) {
102
+ const s = get(name);
103
+ if (s.empty) {
104
+ return [];
105
+ }
106
+ const tonics = s.tonic ? s.notes : s.intervals;
107
+ return (0, import_pcset.modes)(s.chroma).map((chroma, i) => {
108
+ const modeName = get(chroma).name;
109
+ return modeName ? [tonics[i], modeName] : ["", ""];
110
+ }).filter((x) => x[0]);
111
+ }
112
+ function getNoteNameOf(scale2) {
113
+ const names2 = Array.isArray(scale2) ? scaleNotes(scale2) : get(scale2).notes;
114
+ const chromas = names2.map((name) => (0, import_core.note)(name).chroma);
115
+ return (noteOrMidi) => {
116
+ const currNote = typeof noteOrMidi === "number" ? (0, import_core.note)((0, import_note.fromMidi)(noteOrMidi)) : (0, import_core.note)(noteOrMidi);
117
+ const height = currNote.height;
118
+ if (height === void 0)
119
+ return void 0;
120
+ const chroma = height % 12;
121
+ const position = chromas.indexOf(chroma);
122
+ if (position === -1)
123
+ return void 0;
124
+ return (0, import_note.enharmonic)(currNote.name, names2[position]);
125
+ };
126
+ }
127
+ function rangeOf(scale2) {
128
+ const getName = getNoteNameOf(scale2);
129
+ return (fromNote, toNote) => {
130
+ const from = (0, import_core.note)(fromNote).height;
131
+ const to = (0, import_core.note)(toNote).height;
132
+ if (from === void 0 || to === void 0)
133
+ return [];
134
+ return (0, import_collection.range)(from, to).map(getName).filter((x) => x);
135
+ };
136
+ }
137
+ var scale_default = {
138
+ get,
139
+ names,
140
+ extended,
141
+ modeNames,
142
+ reduced,
143
+ scaleChords,
144
+ scaleNotes,
145
+ tokenize,
146
+ rangeOf,
147
+ scale
148
+ };
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ extended,
152
+ get,
153
+ modeNames,
154
+ names,
155
+ rangeOf,
156
+ reduced,
157
+ scale,
158
+ scaleChords,
159
+ scaleNotes,
160
+ tokenize
161
+ });
162
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { rotate, range as nums } from \"@tonaljs/collection\";\nimport { deprecate, note, NoteName, transpose } from \"@tonaljs/core\";\nimport { sortedUniqNames, fromMidi, enharmonic } from \"@tonaljs/note\";\nimport { isSubsetOf, isSupersetOf, modes } from \"@tonaljs/pcset\";\nimport {\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const s = get(name);\n const isSuperset = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\nexport default {\n get,\n names,\n extended,\n modeNames,\n reduced,\n scaleChords,\n scaleNotes,\n tokenize,\n rangeOf,\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["scaleTypeNames","getScaleType","chordTypes","scaleTypes","scale","names","nums"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,132 @@
1
+ // index.ts
2
+ import { all as chordTypes } from "@tonaljs/chord-type";
3
+ import { rotate, range as nums } from "@tonaljs/collection";
4
+ import { deprecate, note, transpose } from "@tonaljs/core";
5
+ import { sortedUniqNames, fromMidi, enharmonic } from "@tonaljs/note";
6
+ import { isSubsetOf, isSupersetOf, modes } from "@tonaljs/pcset";
7
+ import {
8
+ all as scaleTypes,
9
+ get as getScaleType,
10
+ names as scaleTypeNames
11
+ } from "@tonaljs/scale-type";
12
+ var NoScale = {
13
+ empty: true,
14
+ name: "",
15
+ type: "",
16
+ tonic: null,
17
+ setNum: NaN,
18
+ chroma: "",
19
+ normalized: "",
20
+ aliases: [],
21
+ notes: [],
22
+ intervals: []
23
+ };
24
+ function tokenize(name) {
25
+ if (typeof name !== "string") {
26
+ return ["", ""];
27
+ }
28
+ const i = name.indexOf(" ");
29
+ const tonic = note(name.substring(0, i));
30
+ if (tonic.empty) {
31
+ const n = note(name);
32
+ return n.empty ? ["", name] : [n.name, ""];
33
+ }
34
+ const type = name.substring(tonic.name.length + 1);
35
+ return [tonic.name, type.length ? type : ""];
36
+ }
37
+ var names = scaleTypeNames;
38
+ function get(src) {
39
+ const tokens = Array.isArray(src) ? src : tokenize(src);
40
+ const tonic = note(tokens[0]).name;
41
+ const st = getScaleType(tokens[1]);
42
+ if (st.empty) {
43
+ return NoScale;
44
+ }
45
+ const type = st.name;
46
+ const notes = tonic ? st.intervals.map((i) => transpose(tonic, i)) : [];
47
+ const name = tonic ? tonic + " " + type : type;
48
+ return { ...st, name, type, tonic, notes };
49
+ }
50
+ var scale = deprecate("Scale.scale", "Scale.get", get);
51
+ function scaleChords(name) {
52
+ const s = get(name);
53
+ const inScale = isSubsetOf(s.chroma);
54
+ return chordTypes().filter((chord) => inScale(chord.chroma)).map((chord) => chord.aliases[0]);
55
+ }
56
+ function extended(name) {
57
+ const s = get(name);
58
+ const isSuperset = isSupersetOf(s.chroma);
59
+ return scaleTypes().filter((scale2) => isSuperset(scale2.chroma)).map((scale2) => scale2.name);
60
+ }
61
+ function reduced(name) {
62
+ const isSubset = isSubsetOf(get(name).chroma);
63
+ return scaleTypes().filter((scale2) => isSubset(scale2.chroma)).map((scale2) => scale2.name);
64
+ }
65
+ function scaleNotes(notes) {
66
+ const pcset = notes.map((n) => note(n).pc).filter((x) => x);
67
+ const tonic = pcset[0];
68
+ const scale2 = sortedUniqNames(pcset);
69
+ return rotate(scale2.indexOf(tonic), scale2);
70
+ }
71
+ function modeNames(name) {
72
+ const s = get(name);
73
+ if (s.empty) {
74
+ return [];
75
+ }
76
+ const tonics = s.tonic ? s.notes : s.intervals;
77
+ return modes(s.chroma).map((chroma, i) => {
78
+ const modeName = get(chroma).name;
79
+ return modeName ? [tonics[i], modeName] : ["", ""];
80
+ }).filter((x) => x[0]);
81
+ }
82
+ function getNoteNameOf(scale2) {
83
+ const names2 = Array.isArray(scale2) ? scaleNotes(scale2) : get(scale2).notes;
84
+ const chromas = names2.map((name) => note(name).chroma);
85
+ return (noteOrMidi) => {
86
+ const currNote = typeof noteOrMidi === "number" ? note(fromMidi(noteOrMidi)) : note(noteOrMidi);
87
+ const height = currNote.height;
88
+ if (height === void 0)
89
+ return void 0;
90
+ const chroma = height % 12;
91
+ const position = chromas.indexOf(chroma);
92
+ if (position === -1)
93
+ return void 0;
94
+ return enharmonic(currNote.name, names2[position]);
95
+ };
96
+ }
97
+ function rangeOf(scale2) {
98
+ const getName = getNoteNameOf(scale2);
99
+ return (fromNote, toNote) => {
100
+ const from = note(fromNote).height;
101
+ const to = note(toNote).height;
102
+ if (from === void 0 || to === void 0)
103
+ return [];
104
+ return nums(from, to).map(getName).filter((x) => x);
105
+ };
106
+ }
107
+ var scale_default = {
108
+ get,
109
+ names,
110
+ extended,
111
+ modeNames,
112
+ reduced,
113
+ scaleChords,
114
+ scaleNotes,
115
+ tokenize,
116
+ rangeOf,
117
+ scale
118
+ };
119
+ export {
120
+ scale_default as default,
121
+ extended,
122
+ get,
123
+ modeNames,
124
+ names,
125
+ rangeOf,
126
+ reduced,
127
+ scale,
128
+ scaleChords,
129
+ scaleNotes,
130
+ tokenize
131
+ };
132
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { rotate, range as nums } from \"@tonaljs/collection\";\nimport { deprecate, note, NoteName, transpose } from \"@tonaljs/core\";\nimport { sortedUniqNames, fromMidi, enharmonic } from \"@tonaljs/note\";\nimport { isSubsetOf, isSupersetOf, modes } from \"@tonaljs/pcset\";\nimport {\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const s = get(name);\n const isSuperset = isSupersetOf(s.chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\nexport default {\n get,\n names,\n extended,\n modeNames,\n reduced,\n scaleChords,\n scaleNotes,\n tokenize,\n rangeOf,\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["scale","names"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonaljs/scale",
3
- "version": "4.6.4",
3
+ "version": "4.6.10",
4
4
  "description": "Musical scales and its relations",
5
5
  "keywords": [
6
6
  "scale",
@@ -10,23 +10,25 @@
10
10
  "@tonaljs"
11
11
  ],
12
12
  "main": "dist/index.js",
13
- "module": "dist/index.es.js",
13
+ "module": "dist/index.mjs",
14
14
  "files": [
15
15
  "dist"
16
16
  ],
17
17
  "types": "dist/index.d.ts",
18
18
  "dependencies": {
19
- "@tonaljs/chord-type": "^4.6.2",
20
- "@tonaljs/collection": "^4.6.2",
21
- "@tonaljs/core": "^4.6.2",
22
- "@tonaljs/note": "^4.6.2",
23
- "@tonaljs/pcset": "^4.6.2",
24
- "@tonaljs/scale-type": "^4.6.4"
19
+ "@tonaljs/chord-type": "^4.6.10",
20
+ "@tonaljs/collection": "^4.6.10",
21
+ "@tonaljs/core": "^4.6.10",
22
+ "@tonaljs/note": "^4.6.10",
23
+ "@tonaljs/pcset": "^4.6.10",
24
+ "@tonaljs/scale-type": "^4.6.10"
25
25
  },
26
26
  "author": "danigb@gmail.com",
27
27
  "license": "MIT",
28
28
  "publishConfig": {
29
29
  "access": "public"
30
30
  },
31
- "gitHead": "7bb82dd7ce7d97b6a8768041fc4abceeb2542211"
31
+ "scripts": {
32
+ "build": "tsup index.ts --sourcemap --dts --format esm,cjs"
33
+ }
32
34
  }
package/dist/index.es.js DELETED
@@ -1,216 +0,0 @@
1
- import { all } from '@tonaljs/chord-type';
2
- import { rotate, range } from '@tonaljs/collection';
3
- import { deprecate, note, transpose } from '@tonaljs/core';
4
- import { sortedUniqNames, fromMidi, enharmonic } from '@tonaljs/note';
5
- import { isSubsetOf, isSupersetOf, modes } from '@tonaljs/pcset';
6
- import { names as names$1, get as get$1, all as all$1 } from '@tonaljs/scale-type';
7
-
8
- /**
9
- * References:
10
- * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale
11
- * @module scale
12
- */
13
- const NoScale = {
14
- empty: true,
15
- name: "",
16
- type: "",
17
- tonic: null,
18
- setNum: NaN,
19
- chroma: "",
20
- normalized: "",
21
- aliases: [],
22
- notes: [],
23
- intervals: [],
24
- };
25
- /**
26
- * Given a string with a scale name and (optionally) a tonic, split
27
- * that components.
28
- *
29
- * It retuns an array with the form [ name, tonic ] where tonic can be a
30
- * note name or null and name can be any arbitrary string
31
- * (this function doesn"t check if that scale name exists)
32
- *
33
- * @function
34
- * @param {string} name - the scale name
35
- * @return {Array} an array [tonic, name]
36
- * @example
37
- * tokenize("C mixolydean") // => ["C", "mixolydean"]
38
- * tokenize("anything is valid") // => ["", "anything is valid"]
39
- * tokenize() // => ["", ""]
40
- */
41
- function tokenize(name) {
42
- if (typeof name !== "string") {
43
- return ["", ""];
44
- }
45
- const i = name.indexOf(" ");
46
- const tonic = note(name.substring(0, i));
47
- if (tonic.empty) {
48
- const n = note(name);
49
- return n.empty ? ["", name] : [n.name, ""];
50
- }
51
- const type = name.substring(tonic.name.length + 1);
52
- return [tonic.name, type.length ? type : ""];
53
- }
54
- /**
55
- * Get all scale names
56
- * @function
57
- */
58
- const names = names$1;
59
- /**
60
- * Get a Scale from a scale name.
61
- */
62
- function get(src) {
63
- const tokens = Array.isArray(src) ? src : tokenize(src);
64
- const tonic = note(tokens[0]).name;
65
- const st = get$1(tokens[1]);
66
- if (st.empty) {
67
- return NoScale;
68
- }
69
- const type = st.name;
70
- const notes = tonic
71
- ? st.intervals.map((i) => transpose(tonic, i))
72
- : [];
73
- const name = tonic ? tonic + " " + type : type;
74
- return { ...st, name, type, tonic, notes };
75
- }
76
- const scale = deprecate("Scale.scale", "Scale.get", get);
77
- /**
78
- * Get all chords that fits a given scale
79
- *
80
- * @function
81
- * @param {string} name - the scale name
82
- * @return {Array<string>} - the chord names
83
- *
84
- * @example
85
- * scaleChords("pentatonic") // => ["5", "64", "M", "M6", "Madd9", "Msus2"]
86
- */
87
- function scaleChords(name) {
88
- const s = get(name);
89
- const inScale = isSubsetOf(s.chroma);
90
- return all()
91
- .filter((chord) => inScale(chord.chroma))
92
- .map((chord) => chord.aliases[0]);
93
- }
94
- /**
95
- * Get all scales names that are a superset of the given one
96
- * (has the same notes and at least one more)
97
- *
98
- * @function
99
- * @param {string} name
100
- * @return {Array} a list of scale names
101
- * @example
102
- * extended("major") // => ["bebop", "bebop dominant", "bebop major", "chromatic", "ichikosucho"]
103
- */
104
- function extended(name) {
105
- const s = get(name);
106
- const isSuperset = isSupersetOf(s.chroma);
107
- return all$1()
108
- .filter((scale) => isSuperset(scale.chroma))
109
- .map((scale) => scale.name);
110
- }
111
- /**
112
- * Find all scales names that are a subset of the given one
113
- * (has less notes but all from the given scale)
114
- *
115
- * @function
116
- * @param {string} name
117
- * @return {Array} a list of scale names
118
- *
119
- * @example
120
- * reduced("major") // => ["ionian pentatonic", "major pentatonic", "ritusen"]
121
- */
122
- function reduced(name) {
123
- const isSubset = isSubsetOf(get(name).chroma);
124
- return all$1()
125
- .filter((scale) => isSubset(scale.chroma))
126
- .map((scale) => scale.name);
127
- }
128
- /**
129
- * Given an array of notes, return the scale: a pitch class set starting from
130
- * the first note of the array
131
- *
132
- * @function
133
- * @param {string[]} notes
134
- * @return {string[]} pitch classes with same tonic
135
- * @example
136
- * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => ["C"]
137
- * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => ["D", "F#", "A", "C#"]
138
- */
139
- function scaleNotes(notes) {
140
- const pcset = notes.map((n) => note(n).pc).filter((x) => x);
141
- const tonic = pcset[0];
142
- const scale = sortedUniqNames(pcset);
143
- return rotate(scale.indexOf(tonic), scale);
144
- }
145
- /**
146
- * Find mode names of a scale
147
- *
148
- * @function
149
- * @param {string} name - scale name
150
- * @example
151
- * modeNames("C pentatonic") // => [
152
- * ["C", "major pentatonic"],
153
- * ["D", "egyptian"],
154
- * ["E", "malkos raga"],
155
- * ["G", "ritusen"],
156
- * ["A", "minor pentatonic"]
157
- * ]
158
- */
159
- function modeNames(name) {
160
- const s = get(name);
161
- if (s.empty) {
162
- return [];
163
- }
164
- const tonics = s.tonic ? s.notes : s.intervals;
165
- return modes(s.chroma)
166
- .map((chroma, i) => {
167
- const modeName = get(chroma).name;
168
- return modeName ? [tonics[i], modeName] : ["", ""];
169
- })
170
- .filter((x) => x[0]);
171
- }
172
- function getNoteNameOf(scale) {
173
- const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;
174
- const chromas = names.map((name) => note(name).chroma);
175
- return (noteOrMidi) => {
176
- const currNote = typeof noteOrMidi === "number"
177
- ? note(fromMidi(noteOrMidi))
178
- : note(noteOrMidi);
179
- const height = currNote.height;
180
- if (height === undefined)
181
- return undefined;
182
- const chroma = height % 12;
183
- const position = chromas.indexOf(chroma);
184
- if (position === -1)
185
- return undefined;
186
- return enharmonic(currNote.name, names[position]);
187
- };
188
- }
189
- function rangeOf(scale) {
190
- const getName = getNoteNameOf(scale);
191
- return (fromNote, toNote) => {
192
- const from = note(fromNote).height;
193
- const to = note(toNote).height;
194
- if (from === undefined || to === undefined)
195
- return [];
196
- return range(from, to)
197
- .map(getName)
198
- .filter((x) => x);
199
- };
200
- }
201
- var index = {
202
- get,
203
- names,
204
- extended,
205
- modeNames,
206
- reduced,
207
- scaleChords,
208
- scaleNotes,
209
- tokenize,
210
- rangeOf,
211
- // deprecated
212
- scale,
213
- };
214
-
215
- export { index as default, extended, get, modeNames, names, rangeOf, reduced, scale, scaleChords, scaleNotes, tokenize };
216
- //# sourceMappingURL=index.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}