New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tonal-key

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tonal-key - npm Package Compare versions

Comparing version 0.69.9 to 1.0.0-0

coverage/clover.xml

355

build/index.js

@@ -5,18 +5,16 @@ 'use strict';

var tonalNotation = require('tonal-notation');
var tonalTranspose = require('tonal-transpose');
var tonalNote = require('tonal-note');
var tonalRange = require('tonal-range');
var tonalArray = require('tonal-array');
var tonalHarmonizer = require('tonal-harmonizer');
var index = require('tonal-array/index');
var index$1 = require('tonal-note/index');
var index$2 = require('tonal-distance/index');
/**
* _Key_ refers to the tonal system based on the major and minor scales. This is
* is the most common tonal system, but tonality can be present in music
* based in other scales or concepts.
* [![npm version](https://img.shields.io/npm/v/tonal-key.svg?style=flat-square)](https://www.npmjs.com/package/tonal-key)
* [![tonal](https://img.shields.io/badge/tonal-key-yellow.svg?style=flat-square)](https://www.npmjs.com/browse/keyword/tonal)
*
* This is a collection of functions related to keys.
* `tonal-key` is a collection of functions to query about tonal keys.
*
* This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library.
*
* @example
* var key = require('tonal-key')
* const key = require('tonal-key')
* key.scale('E mixolydian') // => [ 'E', 'F#', 'G#', 'A', 'B', 'C#', 'D' ]

@@ -27,138 +25,17 @@ * key.relative('minor', 'C major') // => 'A minor'

*/
const MODES = "major dorian phrygian lydian mixolydian minor locrian ionian aeolian".split(
" "
);
const NUMS = [0, 1, 2, 3, 4, 5, 6, 0, 5];
const NOTES = "C D E F G A B".split(" ");
const CHORDS = "Maj7 m7 m7 Maj7 7 m7 m7b5".split(" ");
const FIFTHS = [0, 2, 4, -1, 1, 3, 5, 0, 3];
// Order matters: use an array
var MODES = ['ionian', 'dorian', 'phrygian', 'lydian', 'mixolydian',
'aeolian', 'locrian', 'major', 'minor'];
// { C: 0, D: 2, E: 4, F: -1, G: 1, A: 3, B: 5 }
var FIFTHS = [0, 2, 4, -1, 1, 3, 5, 0, 3];
var SCALES = [0, 1, 2, 3, 4, 5, 6, 0, 5].map(function (n) {
return tonalHarmonizer.harmonics(tonalArray.rotate(n, ['C', 'D', 'E', 'F', 'G', 'A', 'B']))
});
const modenum = mode => NUMS[MODES.indexOf(mode)];
// PRIVATE
// Given a tonic, mode pair, return the key string
function toKey (t, m) { return !t ? m : t + ' ' + m }
// Given the alterations, return the major key
function majorKey (n) { return toKey(tonalTranspose.trFifths('C', n), 'major') }
// given the mode name, return the alterations
function modeNum (mode) { return FIFTHS[MODES.indexOf(mode)] }
// given a string, return the valid mode it represents or null
function validMode (m) {
m = m.trim().toLowerCase();
return MODES.indexOf(m) === -1 ? null : m
}
/**
* Return the key properties, an object with { tonic, mode }
*
* @param {String} name - the key name
* @return {Key} the key properties object or null if not a valid key
* @example
* var key = require('tonal-key')
* key.props('C3 dorian') // => { tonic: 'C', mode: 'dorian' }
* key.props('dorian') // => { tonic: false, mode: 'dorian' }
* key.props('Ab bebop') // => null
* key.props('blah') // => null
*/
function props (str) {
if (typeof str !== 'string') return null
var ndx = str.indexOf(' ');
var key;
if (ndx === -1) {
var p = tonalNote.pc(str);
key = p ? { tonic: p, mode: 'major' }
: { tonic: false, mode: validMode(str) };
} else {
key = { tonic: tonalNote.pc(str.slice(0, ndx)), mode: validMode(str.slice(ndx + 1)) };
}
return key.mode ? key : null
}
/**
* Test if a given name is a valid key name
*
* @param {String} name
* @param {Boolean}
* @example
* key.isKeyName('C major') // => true
* key.isKeyName('major') // => true
* key.isKeyName('Bb bebop') // => false
*/
function isKeyName (name) {
return props(name) !== null
}
/**
* Get the tonic of a key
*
* @param {String} key - the key
* @return {String} the tonic or false is no tonic, or null if its not a valid key
* @example
* key.tonic('c3 major') // => 'C'
* key.tonic('minor') // => false
* key.tonic('bebop') // null
*/
function tonic (key) {
return (props(key) || key || {}).tonic || null
}
/**
* Get the mode of a key. It can be used to test if its a valid key mode.
*
* @param {String}
* @return {Boolean}
* @example
* key.mode('A dorian') // => 'dorian'
* key.mode('DORIAN') // => 'dorian'
* key.mode('mixophrygian') // => null
*/
function mode (key) {
return (props(key) || key || {}).mode || null
}
/**
* Get relative of a key. Two keys are relative when the have the same
* key signature (for example C major and A minor)
*
* It can be partially applied.
*
* @param {String} mode - the relative destination
* @param {String} key - the key source
* @example
* key.relative('dorian', 'B major') // => 'C# dorian'
* // partial application
* var minor = key.relative('minor')
* minor('C major') // => 'A minor'
* minor('E major') // => 'C# minor'
*/
function relative (rel, key) {
if (arguments.length === 1) return function (k) { return relative(rel, k) }
rel = props(rel);
if (!rel || rel.tonic) return null
key = props(key);
if (!key || !key.tonic) return null
var tonic = tonalTranspose.trFifths(key.tonic, modeNum(rel.mode) - modeNum(key.mode));
return toKey(tonic, rel.mode)
}
/**
* Get a list of the altered notes of a given key. The notes will be in
* the same order than in the key signature.
* @param {String|Nunber} key
* @return {Array}
* @example
* var key = require('tonal-keys')
* key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
*/
function alteredNotes (key) {
var alt = alteration(key);
return alt === null ? null
: alt < 0 ? tonalRange.numeric([-1, alt]).map(tonalTranspose.trFifths('F'))
: tonalRange.numeric([1, alt]).map(tonalTranspose.trFifths('B'))
}
/**
* Get a list of valid mode names. The list of modes will be always in
* increasing order (ionian to locrian)
*
* @function
* @param {Boolean} alias - true to get aliases names

@@ -172,8 +49,8 @@ * @return {Array} an array of strings

*/
function modes (alias) {
return alias ? MODES.slice() : MODES.slice(0, -2)
}
const modeNames = aliases =>
aliases === true ? MODES.slice() : MODES.slice(0, 7);
/**
* Create a major key from alterations
*
* @function

@@ -186,21 +63,58 @@ * @param {Integer} alt - the alteration number (positive sharps, negative flats)

*/
function fromAlter (n) {
return typeof n === 'number' ? majorKey(n) : null
}
const fromAlter = i => index$2.trFifths("C", i) + " major";
const names = (alt = 4) => {
alt = Math.abs(alt);
const result = [];
for (let i = -alt; i <= alt; i++) result.push(fromAlter(i));
return result;
};
const NO_KEY = Object.freeze({
name: null,
tonic: null,
mode: null,
modenum: null,
intervals: [],
scale: [],
alteration: null,
accidentals: null
});
const properties = name => {
const p = tokenize$1(name);
if (p[0] === null) return NO_KEY;
const k = { tonic: p[0], mode: p[1] };
k.name = k.tonic + " " + k.mode;
k.modenum = modenum(k.mode);
const cs = index.rotate(k.modenum, NOTES);
k.intervals = cs.map(index$2.interval(cs[0]));
k.scale = k.intervals.map(index$2.transpose(k.tonic));
k.alteration = index$2.fifths("C", k.tonic) - FIFTHS[MODES.indexOf(k.mode)];
k.accidentals = index$1.altToAcc(k.alteration);
return Object.freeze(k);
};
const memo = (fn, cache = {}) => str => cache[str] || (cache[str] = fn(str));
/**
* Get key name from accidentals
* Return the a key properties object with the following information:
*
* @param {String} acc - the accidentals string
* @return {Key} the key object
* - name: name
* - tonic: key tonic
* - mode: key mode
* - modenum: mode number (0 major, 1 dorian, ...)
* - intervals: the scale intervals
* - scale: the scale notes
* - alteration: alteration number
* - accidentals: accidentals
*
* @function
* @param {String} name - the key name
* @return {Object} the key properties object or null if not a valid key
* @example
* var key = require('tonal-key')
* key.fromAcc('b') // => 'F major'
* key.fromAcc('##') // => 'D major'
* key.props('C3 dorian') // => { tonic: 'C', mode: 'dorian', ... }
*/
function fromAcc (s) {
return tonalNotation.areSharps(s) ? majorKey(s.length)
: tonalNotation.areFlats(s) ? majorKey(-s.length)
: null
}
const props = memo(properties);

@@ -210,2 +124,3 @@ /**

*
* @function
* @param {String|Object} key

@@ -219,7 +134,3 @@ * @return {Array} the key scale

*/
function scale (key) {
var p = props(key);
if (!p || !p.tonic) return null
return tonalHarmonizer.harmonize(SCALES[MODES.indexOf(p.mode)], p.tonic)
}
const scale = str => props(str).scale;

@@ -229,2 +140,4 @@ /**

* sharpen notes (positive) or flaten notes (negative)
*
* @function
* @param {String|Integer} key

@@ -236,38 +149,108 @@ * @return {Integer}

*/
function alteration (key) {
var k = props(key);
if (!k || !k.tonic) return null
var toMajor = modeNum(k.mode);
var toC = tonalNote.pcFifths(k.tonic);
return toC - toMajor
}
const alteration = str => props(str).alteration;
/**
* Get the signature of a key. The signature is a string with sharps or flats.
* Get a list of the altered notes of a given key. The notes will be in
* the same order than in the key signature.
*
* @function
* @param {String} key - the key name
* @return {Array}
* @example
* var key = require('tonal-keys')
* key.signature('A major') // => '###'
* key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
*/
function signature (key) {
return tonalNotation.toAcc(alteration(key))
}
const alteredNotes = name => {
const alt = props(name).alteration;
if (alt === null) return null;
return alt === 0
? []
: alt > 0
? index.range(1, alt).map(index$2.trFifths("B"))
: index.range(-1, alt).map(index$2.trFifths("F"));
};
/**
* An alias for `signature()`
* Get key chords
*
* @function
* @param {String} name - the key name
* @return {Array}
* @example
* key.chords("A major") // => ["AMaj7", "Bm7", "C#m7", "DMaj7", ..,]
*/
var accidentals = signature;
const chords = str => {
const p = props(str);
if (!p.name) return [];
const chords = index.rotate(p.modenum, CHORDS);
return p.scale.map((tonic, i) => tonic + chords[i]);
};
/**
* Get secondary dominant key chords
*
* @function
* @param {String} name - the key name
* @return {Array}
* @example
* key.secDomChords("A major") // => ["E7", "F#7", ...]
*/
const secDomChords = name => {
const p = props(name);
if (!p.name) return [];
return p.scale.map(t => index$2.transpose(t, "P5") + "7");
};
/**
* Get relative of a key. Two keys are relative when the have the same
* key signature (for example C major and A minor)
*
* It can be partially applied.
*
* @function
* @param {String} mode - the relative destination
* @param {String} key - the key source
* @example
* key.relative('dorian', 'B major') // => 'C# dorian'
* // partial application
* var minor = key.relative('minor')
* minor('C major') // => 'A minor'
* minor('E major') // => 'C# minor'
*/
const relative = (mode, key) => {
if (arguments.length === 1) return key => relative(mode, key);
const num = modenum(mode.toLowerCase());
if (num === undefined) return null;
const k = props(key);
if (k.name === null) return null;
return index$2.trFifths(k.tonic, FIFTHS[num] - FIFTHS[k.modenum]) + " " + mode;
};
/**
* Split the key name into its components (pitch class tonic and mode name)
*
* @function
* @param {String} name
* @return {Array} an array in the form [tonic, key]
* @example
* key.tokenize('C major') // => ['C', 'major']
*/
const tokenize$1 = name => {
const p = index$1.tokenize(name);
p[3] = p[3].toLowerCase();
if (p[0] === "" || MODES.indexOf(p[3]) === -1) return [null, null];
return [p[0] + p[1], p[3]];
};
exports.modeNames = modeNames;
exports.fromAlter = fromAlter;
exports.names = names;
exports.props = props;
exports.isKeyName = isKeyName;
exports.tonic = tonic;
exports.mode = mode;
exports.relative = relative;
exports.alteredNotes = alteredNotes;
exports.modes = modes;
exports.fromAlter = fromAlter;
exports.fromAcc = fromAcc;
exports.scale = scale;
exports.alteration = alteration;
exports.signature = signature;
exports.accidentals = accidentals;
exports.alteredNotes = alteredNotes;
exports.chords = chords;
exports.secDomChords = secDomChords;
exports.relative = relative;
exports.tokenize = tokenize$1;
/**
* _Key_ refers to the tonal system based on the major and minor scales. This is
* is the most common tonal system, but tonality can be present in music
* based in other scales or concepts.
* [![npm version](https://img.shields.io/npm/v/tonal-key.svg?style=flat-square)](https://www.npmjs.com/package/tonal-key)
* [![tonal](https://img.shields.io/badge/tonal-key-yellow.svg?style=flat-square)](https://www.npmjs.com/browse/keyword/tonal)
*
* This is a collection of functions related to keys.
* `tonal-key` is a collection of functions to query about tonal keys.
*
* This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library.
*
* @example
* var key = require('tonal-key')
* const key = require('tonal-key')
* key.scale('E mixolydian') // => [ 'E', 'F#', 'G#', 'A', 'B', 'C#', 'D' ]

@@ -15,145 +16,21 @@ * key.relative('minor', 'C major') // => 'A minor'

*/
import { rotate, range } from "tonal-array/index";
import { tokenize as split, altToAcc } from "tonal-note/index";
import { trFifths, fifths, interval, transpose } from "tonal-distance/index";
import { areFlats, areSharps, toAcc } from 'tonal-notation'
import { trFifths } from 'tonal-transpose'
import { pc, pcFifths } from 'tonal-note'
import { numeric } from 'tonal-range'
import { rotate } from 'tonal-array'
import { harmonics, harmonize } from 'tonal-harmonizer'
const MODES = "major dorian phrygian lydian mixolydian minor locrian ionian aeolian".split(
" "
);
const NUMS = [0, 1, 2, 3, 4, 5, 6, 0, 5];
const NOTES = "C D E F G A B".split(" ");
const CHORDS = "Maj7 m7 m7 Maj7 7 m7 m7b5".split(" ");
const FIFTHS = [0, 2, 4, -1, 1, 3, 5, 0, 3];
// Order matters: use an array
var MODES = ['ionian', 'dorian', 'phrygian', 'lydian', 'mixolydian',
'aeolian', 'locrian', 'major', 'minor']
// { C: 0, D: 2, E: 4, F: -1, G: 1, A: 3, B: 5 }
var FIFTHS = [0, 2, 4, -1, 1, 3, 5, 0, 3]
var SCALES = [0, 1, 2, 3, 4, 5, 6, 0, 5].map(function (n) {
return harmonics(rotate(n, ['C', 'D', 'E', 'F', 'G', 'A', 'B']))
})
const modenum = mode => NUMS[MODES.indexOf(mode)];
// PRIVATE
// Given a tonic, mode pair, return the key string
function toKey (t, m) { return !t ? m : t + ' ' + m }
// Given the alterations, return the major key
function majorKey (n) { return toKey(trFifths('C', n), 'major') }
// given the mode name, return the alterations
function modeNum (mode) { return FIFTHS[MODES.indexOf(mode)] }
// given a string, return the valid mode it represents or null
function validMode (m) {
m = m.trim().toLowerCase()
return MODES.indexOf(m) === -1 ? null : m
}
/**
* Return the key properties, an object with { tonic, mode }
*
* @param {String} name - the key name
* @return {Key} the key properties object or null if not a valid key
* @example
* var key = require('tonal-key')
* key.props('C3 dorian') // => { tonic: 'C', mode: 'dorian' }
* key.props('dorian') // => { tonic: false, mode: 'dorian' }
* key.props('Ab bebop') // => null
* key.props('blah') // => null
*/
export function props (str) {
if (typeof str !== 'string') return null
var ndx = str.indexOf(' ')
var key
if (ndx === -1) {
var p = pc(str)
key = p ? { tonic: p, mode: 'major' }
: { tonic: false, mode: validMode(str) }
} else {
key = { tonic: pc(str.slice(0, ndx)), mode: validMode(str.slice(ndx + 1)) }
}
return key.mode ? key : null
}
/**
* Test if a given name is a valid key name
*
* @param {String} name
* @param {Boolean}
* @example
* key.isKeyName('C major') // => true
* key.isKeyName('major') // => true
* key.isKeyName('Bb bebop') // => false
*/
export function isKeyName (name) {
return props(name) !== null
}
/**
* Get the tonic of a key
*
* @param {String} key - the key
* @return {String} the tonic or false is no tonic, or null if its not a valid key
* @example
* key.tonic('c3 major') // => 'C'
* key.tonic('minor') // => false
* key.tonic('bebop') // null
*/
export function tonic (key) {
return (props(key) || key || {}).tonic || null
}
/**
* Get the mode of a key. It can be used to test if its a valid key mode.
*
* @param {String}
* @return {Boolean}
* @example
* key.mode('A dorian') // => 'dorian'
* key.mode('DORIAN') // => 'dorian'
* key.mode('mixophrygian') // => null
*/
export function mode (key) {
return (props(key) || key || {}).mode || null
}
/**
* Get relative of a key. Two keys are relative when the have the same
* key signature (for example C major and A minor)
*
* It can be partially applied.
*
* @param {String} mode - the relative destination
* @param {String} key - the key source
* @example
* key.relative('dorian', 'B major') // => 'C# dorian'
* // partial application
* var minor = key.relative('minor')
* minor('C major') // => 'A minor'
* minor('E major') // => 'C# minor'
*/
export function relative (rel, key) {
if (arguments.length === 1) return function (k) { return relative(rel, k) }
rel = props(rel)
if (!rel || rel.tonic) return null
key = props(key)
if (!key || !key.tonic) return null
var tonic = trFifths(key.tonic, modeNum(rel.mode) - modeNum(key.mode))
return toKey(tonic, rel.mode)
}
/**
* Get a list of the altered notes of a given key. The notes will be in
* the same order than in the key signature.
* @param {String|Nunber} key
* @return {Array}
* @example
* var key = require('tonal-keys')
* key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
*/
export function alteredNotes (key) {
var alt = alteration(key)
return alt === null ? null
: alt < 0 ? numeric([-1, alt]).map(trFifths('F'))
: numeric([1, alt]).map(trFifths('B'))
}
/**
* Get a list of valid mode names. The list of modes will be always in
* increasing order (ionian to locrian)
*
* @function
* @param {Boolean} alias - true to get aliases names

@@ -167,8 +44,8 @@ * @return {Array} an array of strings

*/
export function modes (alias) {
return alias ? MODES.slice() : MODES.slice(0, -2)
}
export const modeNames = aliases =>
aliases === true ? MODES.slice() : MODES.slice(0, 7);
/**
* Create a major key from alterations
*
* @function

@@ -181,21 +58,58 @@ * @param {Integer} alt - the alteration number (positive sharps, negative flats)

*/
export function fromAlter (n) {
return typeof n === 'number' ? majorKey(n) : null
}
export const fromAlter = i => trFifths("C", i) + " major";
export const names = (alt = 4) => {
alt = Math.abs(alt);
const result = [];
for (let i = -alt; i <= alt; i++) result.push(fromAlter(i));
return result;
};
const NO_KEY = Object.freeze({
name: null,
tonic: null,
mode: null,
modenum: null,
intervals: [],
scale: [],
alteration: null,
accidentals: null
});
const properties = name => {
const p = tokenize(name);
if (p[0] === null) return NO_KEY;
const k = { tonic: p[0], mode: p[1] };
k.name = k.tonic + " " + k.mode;
k.modenum = modenum(k.mode);
const cs = rotate(k.modenum, NOTES);
k.intervals = cs.map(interval(cs[0]));
k.scale = k.intervals.map(transpose(k.tonic));
k.alteration = fifths("C", k.tonic) - FIFTHS[MODES.indexOf(k.mode)];
k.accidentals = altToAcc(k.alteration);
return Object.freeze(k);
};
const memo = (fn, cache = {}) => str => cache[str] || (cache[str] = fn(str));
/**
* Get key name from accidentals
* Return the a key properties object with the following information:
*
* @param {String} acc - the accidentals string
* @return {Key} the key object
* - name: name
* - tonic: key tonic
* - mode: key mode
* - modenum: mode number (0 major, 1 dorian, ...)
* - intervals: the scale intervals
* - scale: the scale notes
* - alteration: alteration number
* - accidentals: accidentals
*
* @function
* @param {String} name - the key name
* @return {Object} the key properties object or null if not a valid key
* @example
* var key = require('tonal-key')
* key.fromAcc('b') // => 'F major'
* key.fromAcc('##') // => 'D major'
* key.props('C3 dorian') // => { tonic: 'C', mode: 'dorian', ... }
*/
export function fromAcc (s) {
return areSharps(s) ? majorKey(s.length)
: areFlats(s) ? majorKey(-s.length)
: null
}
export const props = memo(properties);

@@ -205,2 +119,3 @@ /**

*
* @function
* @param {String|Object} key

@@ -214,7 +129,3 @@ * @return {Array} the key scale

*/
export function scale (key) {
var p = props(key)
if (!p || !p.tonic) return null
return harmonize(SCALES[MODES.indexOf(p.mode)], p.tonic)
}
export const scale = str => props(str).scale;

@@ -224,2 +135,4 @@ /**

* sharpen notes (positive) or flaten notes (negative)
*
* @function
* @param {String|Integer} key

@@ -231,24 +144,96 @@ * @return {Integer}

*/
export function alteration (key) {
var k = props(key)
if (!k || !k.tonic) return null
var toMajor = modeNum(k.mode)
var toC = pcFifths(k.tonic)
return toC - toMajor
}
export const alteration = str => props(str).alteration;
/**
* Get the signature of a key. The signature is a string with sharps or flats.
* Get a list of the altered notes of a given key. The notes will be in
* the same order than in the key signature.
*
* @function
* @param {String} key - the key name
* @return {Array}
* @example
* var key = require('tonal-keys')
* key.signature('A major') // => '###'
* key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
*/
export function signature (key) {
return toAcc(alteration(key))
}
export const alteredNotes = name => {
const alt = props(name).alteration;
if (alt === null) return null;
return alt === 0
? []
: alt > 0
? range(1, alt).map(trFifths("B"))
: range(-1, alt).map(trFifths("F"));
};
/**
* An alias for `signature()`
* Get key chords
*
* @function
* @param {String} name - the key name
* @return {Array}
* @example
* key.chords("A major") // => ["AMaj7", "Bm7", "C#m7", "DMaj7", ..,]
*/
export var accidentals = signature
export const chords = str => {
const p = props(str);
if (!p.name) return [];
const chords = rotate(p.modenum, CHORDS);
return p.scale.map((tonic, i) => tonic + chords[i]);
};
/**
* Get secondary dominant key chords
*
* @function
* @param {String} name - the key name
* @return {Array}
* @example
* key.secDomChords("A major") // => ["E7", "F#7", ...]
*/
export const secDomChords = name => {
const p = props(name);
if (!p.name) return [];
return p.scale.map(t => transpose(t, "P5") + "7");
};
/**
* Get relative of a key. Two keys are relative when the have the same
* key signature (for example C major and A minor)
*
* It can be partially applied.
*
* @function
* @param {String} mode - the relative destination
* @param {String} key - the key source
* @example
* key.relative('dorian', 'B major') // => 'C# dorian'
* // partial application
* var minor = key.relative('minor')
* minor('C major') // => 'A minor'
* minor('E major') // => 'C# minor'
*/
export const relative = (mode, key) => {
if (arguments.length === 1) return key => relative(mode, key);
const num = modenum(mode.toLowerCase());
if (num === undefined) return null;
const k = props(key);
if (k.name === null) return null;
return trFifths(k.tonic, FIFTHS[num] - FIFTHS[k.modenum]) + " " + mode;
};
/**
* Split the key name into its components (pitch class tonic and mode name)
*
* @function
* @param {String} name
* @return {Array} an array in the form [tonic, key]
* @example
* key.tokenize('C major') // => ['C', 'major']
*/
export const tokenize = name => {
const p = split(name);
p[3] = p[3].toLowerCase();
if (p[0] === "" || MODES.indexOf(p[3]) === -1) return [null, null];
return [p[0] + p[1], p[3]];
};
{
"name": "tonal-key",
"version": "0.69.9",
"version": "1.0.0-0",
"description": "Conversion between key numbers and note names",

@@ -12,2 +12,3 @@ "repository": "https://github.com/danigb/tonal/packages/key",

"scripts": {
"docs": "jsdoc2md -d 1 --name-format --member-index-format list index.js > README.md",
"test": "jest --coverage"

@@ -20,9 +21,16 @@ },

"dependencies": {
"tonal-array": "^0.69.7",
"tonal-harmonizer": "^0.69.7",
"tonal-notation": "^0.69.7",
"tonal-note": "^0.69.9",
"tonal-range": "^0.69.9",
"tonal-transpose": "^0.69.7"
"tonal-array": "^1.0.0-0",
"tonal-distance": "^1.0.0-0",
"tonal-note": "^1.0.0-0"
},
"babel": {
"presets": [
"es2015"
]
},
"jest": {
"transformIgnorePatterns": [
"<rootDir>/node_modules/(?!tonal)"
]
}
}

@@ -1,262 +0,214 @@

# tonal-key [![npm version](https://img.shields.io/npm/v/tonal-key.svg)](https://www.npmjs.com/package/tonal-key)
<a name="module_key"></a>
[![tonal](https://img.shields.io/badge/tonal-key-yellow.svg)](https://www.npmjs.com/browse/keyword/tonal)
# key
[![npm version](https://img.shields.io/npm/v/tonal-key.svg?style=flat-square)](https://www.npmjs.com/package/tonal-key)
[![tonal](https://img.shields.io/badge/tonal-key-yellow.svg?style=flat-square)](https://www.npmjs.com/browse/keyword/tonal)
`tonal-key` is a collection of functions to create and manipulate music keys.
`tonal-key` is a collection of functions to query about tonal keys.
This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library.
You can install via npm: `npm i --save tonal-key`
**Example**
```js
const key = require('tonal-key')
key.scale('E mixolydian') // => [ 'E', 'F#', 'G#', 'A', 'B', 'C#', 'D' ]
key.relative('minor', 'C major') // => 'A minor'
```
## API Reference
* [key](#module_key)
* [`.modeNames(alias)`](#module_key.modeNames) ⇒ <code>Array</code>
* [`.fromAlter(alt)`](#module_key.fromAlter) ⇒ <code>Key</code>
* [`.props(name)`](#module_key.props) ⇒ <code>Object</code>
* [`.scale(key)`](#module_key.scale) ⇒ <code>Array</code>
* [`.alteration(key)`](#module_key.alteration) ⇒ <code>Integer</code>
* [`.alteredNotes(key)`](#module_key.alteredNotes) ⇒ <code>Array</code>
* [`.chords(name)`](#module_key.chords) ⇒ <code>Array</code>
* [`.secDomChords(name)`](#module_key.secDomChords) ⇒ <code>Array</code>
* [`.relative(mode, key)`](#module_key.relative)
* [`.tokenize(name)`](#module_key.tokenize) ⇒ <code>Array</code>
<dl>
<dt><a href="#scale">scale(key)</a> ⇒ <code>Array</code></dt>
<dd><p>Get scale of a key</p>
</dd>
<dt><a href="#relative">relative(mode, key)</a></dt>
<dd><p>Get relative of a key. It can be partially applied.</p>
</dd>
<dt><a href="#alteredNotes">alteredNotes(key)</a> ⇒ <code>Array</code></dt>
<dd><p>Get a list of the altered notes of a given key. The notes will be in
the same order than in the key signature.</p>
</dd>
<dt><a href="#names">names(alias)</a> ⇒ <code>Array</code></dt>
<dd><p>Get a list of valid mode names. The list of modes will be always in
increasing order (ionian to locrian)</p>
</dd>
<dt><a href="#isKeyMode">isKeyMode(m)</a> ⇒ <code>Boolean</code></dt>
<dd><p>Check if the given string is a valid mode name</p>
</dd>
<dt><a href="#build">build(tonic, mode)</a> ⇒ <code>Key</code></dt>
<dd><p>Build a key object from tonic a mode.</p>
<p>A key object is an array with the mode name and the tonic (or false if
no tonic specified)</p>
</dd>
<dt><a href="#fromAlter">fromAlter(alt)</a> ⇒ <code>Key</code></dt>
<dd><p>Create a major key from alterations</p>
</dd>
<dt><a href="#fromAcc">fromAcc(acc)</a> ⇒ <code>Key</code></dt>
<dd><p>Create a major key from accidentals</p>
</dd>
<dt><a href="#fromName">fromName(name)</a> ⇒ <code>Key</code></dt>
<dd><p>Create a key from key name</p>
</dd>
<dt><a href="#asKey">asKey(obj)</a> ⇒ <code>Key</code></dt>
<dd><p>Try to interpret the given object as a key. Given an object it will try to
parse as if it were a name, accidentals or alterations.</p>
</dd>
<dt><a href="#alteration">alteration(key)</a> ⇒ <code>Integer</code></dt>
<dd><p>Get key alteration. The alteration is a number indicating the number of
sharpen notes (positive) or flaten notes (negative)</p>
</dd>
<dt><a href="#signature">signature()</a></dt>
<dd><p>Get the signature of a key. The signature is a string with sharps or flats.</p>
</dd>
<dt><a href="#accidentals">accidentals()</a></dt>
<dd><p>An alias for <code>signature()</code></p>
</dd>
</dl>
<a name="module_key.modeNames"></a>
<a name="scale"></a>
## `key.modeNames(alias)` ⇒ <code>Array</code>
Get a list of valid mode names. The list of modes will be always in
increasing order (ionian to locrian)
## scale(key) ⇒ <code>Array</code>
Get scale of a key
**Kind**: static method of [<code>key</code>](#module_key)
**Returns**: <code>Array</code> - an array of strings
**Kind**: global function
**Returns**: <code>Array</code> - the key scale
| Param | Type | Description |
| --- | --- | --- |
| alias | <code>Boolean</code> | true to get aliases names |
| Param | Type |
| --- | --- |
| key | <code>String</code> &#124; <code>Object</code> |
**Example**
```js
key.modes() // => [ 'ionian', 'dorian', 'phrygian', 'lydian',
// 'mixolydian', 'aeolian', 'locrian' ]
key.modes(true) // => [ 'ionian', 'dorian', 'phrygian', 'lydian',
// 'mixolydian', 'aeolian', 'locrian', 'major', 'minor' ]
```
<a name="module_key.fromAlter"></a>
## `key.fromAlter(alt)` ⇒ <code>Key</code>
Create a major key from alterations
**Kind**: static method of [<code>key</code>](#module_key)
**Returns**: <code>Key</code> - the key object
| Param | Type | Description |
| --- | --- | --- |
| alt | <code>Integer</code> | the alteration number (positive sharps, negative flats) |
**Example**
```js
var key = require('tonal-key')
key.scale('A major') // => [ 'A', 'B', 'C#', 'D', 'E', 'F#', 'G#' ]
key.scale('Bb minor') // => [ 'Bb', 'C', 'Db', 'Eb', 'F', 'Gb', 'Ab' ]
key.scale('C dorian') // => [ 'C', 'D', 'Eb', 'F', 'G', 'A', 'Bb' ]
key.scale('E mixolydian') // => [ 'E', 'F#', 'G#', 'A', 'B', 'C#', 'D' ]
key.fromAlter(2) // => 'D major'
```
<a name="relative"></a>
<a name="module_key.props"></a>
## relative(mode, key)
Get relative of a key. It can be partially applied.
## `key.props(name)` ⇒ <code>Object</code>
Return the a key properties object with the following information:
**Kind**: global function
- name: name
- tonic: key tonic
- mode: key mode
- modenum: mode number (0 major, 1 dorian, ...)
- intervals: the scale intervals
- scale: the scale notes
- alteration: alteration number
- accidentals: accidentals
**Kind**: static method of [<code>key</code>](#module_key)
**Returns**: <code>Object</code> - the key properties object or null if not a valid key
| Param | Type | Description |
| --- | --- | --- |
| mode | <code>String</code> | the relative destination |
| key | <code>String</code> | the key source |
| name | <code>String</code> | the key name |
**Example**
```js
var key = require('tonal-keys')
key.relative('dorian', 'C major') // => ['dorian', 'D']
// partially application
var minor = key.relative('minor')
minor('C major') // => ['minor', 'A']
var key = require('tonal-key')
key.props('C3 dorian') // => { tonic: 'C', mode: 'dorian', ... }
```
<a name="alteredNotes"></a>
<a name="module_key.scale"></a>
## alteredNotes(key) ⇒ <code>Array</code>
Get a list of the altered notes of a given key. The notes will be in
the same order than in the key signature.
## `key.scale(key)` ⇒ <code>Array</code>
Get scale of a key
**Kind**: global function
**Kind**: static method of [<code>key</code>](#module_key)
**Returns**: <code>Array</code> - the key scale
| Param | Type |
| --- | --- |
| key | <code>String</code> &#124; <code>Nunber</code> |
| key | <code>String</code> \| <code>Object</code> |
**Example**
```js
var key = require('tonal-keys')
key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
key.scale('A major') // => [ 'A', 'B', 'C#', 'D', 'E', 'F#', 'G#' ]
key.scale('Bb minor') // => [ 'Bb', 'C', 'Db', 'Eb', 'F', 'Gb', 'Ab' ]
key.scale('C dorian') // => [ 'C', 'D', 'Eb', 'F', 'G', 'A', 'Bb' ]
key.scale('E mixolydian') // => [ 'E', 'F#', 'G#', 'A', 'B', 'C#', 'D' ]
```
<a name="names"></a>
<a name="module_key.alteration"></a>
## names(alias) ⇒ <code>Array</code>
Get a list of valid mode names. The list of modes will be always in
increasing order (ionian to locrian)
## `key.alteration(key)` ⇒ <code>Integer</code>
Get key alteration. The alteration is a number indicating the number of
sharpen notes (positive) or flaten notes (negative)
**Kind**: global function
**Returns**: <code>Array</code> - an array of strings
**Kind**: static method of [<code>key</code>](#module_key)
| Param | Type | Description |
| --- | --- | --- |
| alias | <code>Boolean</code> | true to get aliases names |
<a name="isKeyMode"></a>
## isKeyMode(m) ⇒ <code>Boolean</code>
Check if the given string is a valid mode name
**Kind**: global function
| Param | Type |
| --- | --- |
| m | <code>String</code> |
| key | <code>String</code> \| <code>Integer</code> |
<a name="build"></a>
**Example**
```js
var key = require('tonal-keys')
key.alteration('A major') // => 3
```
<a name="module_key.alteredNotes"></a>
## build(tonic, mode) ⇒ <code>Key</code>
Build a key object from tonic a mode.
## `key.alteredNotes(key)` ⇒ <code>Array</code>
Get a list of the altered notes of a given key. The notes will be in
the same order than in the key signature.
A key object is an array with the mode name and the tonic (or false if
no tonic specified)
**Kind**: static method of [<code>key</code>](#module_key)
**Kind**: global function
**Returns**: <code>Key</code> - a key data object
| Param | Type | Description |
| --- | --- | --- |
| tonic | <code>String</code> | the key tonic (or null or false to no tonic) |
| mode | <code>String</code> | the keymode |
| key | <code>String</code> | the key name |
**Example**
```js
var key = require('tonal-key')
key.build('g3', 'minor') // => ['minor', 'G']
key.build(false, 'locrian') // => ['locrian', false]
var key = require('tonal-keys')
key.alteredNotes('Eb major') // => [ 'Bb', 'Eb', 'Ab' ]
```
<a name="fromAlter"></a>
<a name="module_key.chords"></a>
## fromAlter(alt) ⇒ <code>Key</code>
Create a major key from alterations
## `key.chords(name)` ⇒ <code>Array</code>
Get key chords
**Kind**: global function
**Returns**: <code>Key</code> - the key object
**Kind**: static method of [<code>key</code>](#module_key)
| Param | Type | Description |
| --- | --- | --- |
| alt | <code>Integer</code> | the alteration number (positive sharps, negative flats) |
| name | <code>String</code> | the key name |
**Example**
```js
var key = require('tonal-key')
key.fromAlter(2) // => ['major', 'D']
key.chords("A major") // => ["AMaj7", "Bm7", "C#m7", "DMaj7", ..,]
```
<a name="fromAcc"></a>
<a name="module_key.secDomChords"></a>
## fromAcc(acc) ⇒ <code>Key</code>
Create a major key from accidentals
## `key.secDomChords(name)` ⇒ <code>Array</code>
Get secondary dominant key chords
**Kind**: global function
**Returns**: <code>Key</code> - the key object
**Kind**: static method of [<code>key</code>](#module_key)
| Param | Type | Description |
| --- | --- | --- |
| acc | <code>String</code> | the accidentals string |
| name | <code>String</code> | the key name |
**Example**
```js
var key = require('tonal-key')
key.fromAlter('bb') // => ['major', 'Bb']
key.secDomChords("A major") // => ["E7", "F#7", ...]
```
<a name="fromName"></a>
<a name="module_key.relative"></a>
## fromName(name) ⇒ <code>Key</code>
Create a key from key name
## `key.relative(mode, key)`
Get relative of a key. Two keys are relative when the have the same
key signature (for example C major and A minor)
**Kind**: global function
**Returns**: <code>Key</code> - the key object or null if not valid key
It can be partially applied.
**Kind**: static method of [<code>key</code>](#module_key)
| Param | Type | Description |
| --- | --- | --- |
| name | <code>String</code> | the key name |
| mode | <code>String</code> | the relative destination |
| key | <code>String</code> | the key source |
**Example**
```js
var key = require('tonal-key')
key.fromName('C3 dorian') // => ['dorian', 'C']
key.fromName('blah') // => null
key.relative('dorian', 'B major') // => 'C# dorian'
// partial application
var minor = key.relative('minor')
minor('C major') // => 'A minor'
minor('E major') // => 'C# minor'
```
<a name="asKey"></a>
<a name="module_key.tokenize"></a>
## asKey(obj) ⇒ <code>Key</code>
Try to interpret the given object as a key. Given an object it will try to
parse as if it were a name, accidentals or alterations.
## `key.tokenize(name)` ⇒ <code>Array</code>
Split the key name into its components (pitch class tonic and mode name)
**Kind**: global function
**Returns**: <code>Key</code> - the key object or null
**Kind**: static method of [<code>key</code>](#module_key)
**Returns**: <code>Array</code> - an array in the form [tonic, key]
| Param | Type |
| --- | --- |
| obj | <code>Object</code> |
| name | <code>String</code> |
<a name="alteration"></a>
## alteration(key) ⇒ <code>Integer</code>
Get key alteration. The alteration is a number indicating the number of
sharpen notes (positive) or flaten notes (negative)
**Kind**: global function
| Param | Type |
| --- | --- |
| key | <code>String</code> &#124; <code>Integer</code> |
**Example**
```js
var key = require('tonal-keys')
key.alteration('A major') // => 3
key.tokenize('C major') // => ['C', 'major']
```
<a name="signature"></a>
## signature()
Get the signature of a key. The signature is a string with sharps or flats.
**Kind**: global function
**Example**
```js
var key = require('tonal-keys')
key.signature('A major') // => '###'
```
<a name="accidentals"></a>
## accidentals()
An alias for `signature()`
**Kind**: global function
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc