tonal-note
Advanced tools
Comparing version 2.1.0 to 2.1.2
436
build/es5.js
@@ -5,391 +5,127 @@ 'use strict'; | ||
/** | ||
* [![npm version](https://img.shields.io/npm/v/tonal-note.svg)](https://www.npmjs.com/package/tonal-note) | ||
* [![tonal](https://img.shields.io/badge/tonal-note-yellow.svg)](https://www.npmjs.com/browse/keyword/tonal) | ||
* | ||
* `tonal-note` is a collection of functions to manipulate musical notes in scientific notation | ||
* | ||
* This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library. | ||
* | ||
* ## Usage | ||
* | ||
* ```js | ||
* import * as Note from "tonal-note" | ||
* // or const Note = require("tonal-note") | ||
* Note.name("bb2") // => "Bb2" | ||
* Note.chroma("bb2") // => 10 | ||
* Note.midi("a4") // => 69 | ||
* Note.freq("a4") // => 440 | ||
* Note.oct("G3") // => 3 | ||
* | ||
* // part of tonal | ||
* const Tonal = require("tonal") | ||
* // or import Note from "tonal" | ||
* Tonal.Note.midi("d4") // => 62 | ||
* ``` | ||
* | ||
* ## Install | ||
* | ||
* [![npm install tonal-note](https://nodei.co/npm/tonal-note.png?mini=true)](https://npmjs.org/package/tonal-note/) | ||
* | ||
* ## API Documentation | ||
* | ||
* @module Note | ||
*/ | ||
var NAMES = "C C# Db D D# Eb E F F# Gb G G# Ab A A# Bb B".split(" "); | ||
/** | ||
* Get a list of note names (pitch classes) within a octave | ||
* | ||
* @param {string} accTypes - (Optional, by default " b#"). A string with the | ||
* accidentals types: " " means no accidental, "#" means sharps, "b" mean flats, | ||
* can be combined (see examples) | ||
* @return {Array} | ||
* @example | ||
* Note.names(" b") // => [ "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" ] | ||
* Note.names(" #") // => [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ] | ||
*/ | ||
var names = function (accTypes) { return typeof accTypes !== "string" | ||
? NAMES.slice() | ||
: NAMES.filter(function (n) { | ||
var acc = n[1] || " "; | ||
return accTypes.indexOf(acc) !== -1; | ||
}); }; | ||
var names = function (accTypes) { | ||
return typeof accTypes !== "string" | ||
? NAMES.slice() | ||
: NAMES.filter(function (n) { | ||
var acc = n[1] || " "; | ||
return accTypes.indexOf(acc) !== -1; | ||
}); | ||
}; | ||
var SHARPS = names(" #"); | ||
var FLATS = names(" b"); | ||
var REGEX = /^([a-gA-G]?)(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)$/; | ||
/** | ||
* Split a string into tokens related to note parts. | ||
* It returns an array of strings `[letter, accidental, octave, modifier]` | ||
* | ||
* It always returns an array | ||
* | ||
* @param {String} str | ||
* @return {Array} an array of note tokens | ||
* @example | ||
* Note.tokenize("C#2") // => ["C", "#", "2", ""] | ||
* Note.tokenize("Db3 major") // => ["D", "b", "3", "major"] | ||
* Note.tokenize("major") // => ["", "", "", "major"] | ||
* Note.tokenize("##") // => ["", "##", "", ""] | ||
* Note.tokenize() // => ["", "", "", ""] | ||
*/ | ||
function tokenize(str) { | ||
if (typeof str !== "string") { str = ""; } | ||
var m = REGEX.exec(str); | ||
if (!m) { return null; } | ||
return [m[1].toUpperCase(), m[2].replace(/x/g, "##"), m[3], m[4]]; | ||
if (typeof str !== "string") | ||
str = ""; | ||
var m = REGEX.exec(str); | ||
return [m[1].toUpperCase(), m[2].replace(/x/g, "##"), m[3], m[4]]; | ||
} | ||
var NO_NOTE = Object.freeze({ | ||
pc: null, | ||
name: null, | ||
step: null, | ||
alt: null, | ||
oct: null, | ||
octStr: null, | ||
chroma: null, | ||
midi: null, | ||
freq: null | ||
pc: null, | ||
name: null, | ||
step: null, | ||
alt: null, | ||
oct: null, | ||
octStr: null, | ||
chroma: null, | ||
midi: null, | ||
freq: null | ||
}); | ||
var SEMI = [0, 2, 4, 5, 7, 9, 11]; | ||
var properties = function (str) { | ||
var tokens = tokenize(str); | ||
if (tokens[0] === "" || tokens[3] !== "") { return NO_NOTE; } | ||
var letter = tokens[0]; | ||
var acc = tokens[1]; | ||
var octStr = tokens[2]; | ||
var p = { letter: letter, acc: acc, octStr: octStr }; | ||
p.pc = p.letter + p.acc; | ||
p.name = p.pc + octStr; | ||
p.step = (p.letter.charCodeAt(0) + 3) % 7; | ||
p.alt = p.acc[0] === "b" ? -p.acc.length : p.acc.length; | ||
p.oct = octStr.length ? +octStr : null; | ||
p.chroma = (SEMI[p.step] + p.alt + 120) % 12; | ||
p.midi = p.oct !== null ? SEMI[p.step] + p.alt + 12 * (p.oct + 1) : null; | ||
p.freq = midiToFreq(p.midi); | ||
return Object.freeze(p); | ||
var tokens = tokenize(str); | ||
if (tokens[0] === "" || tokens[3] !== "") | ||
return NO_NOTE; | ||
var letter = tokens[0], acc = tokens[1], octStr = tokens[2]; | ||
var p = { | ||
letter: letter, | ||
acc: acc, | ||
octStr: octStr, | ||
pc: letter + acc, | ||
name: letter + acc + octStr, | ||
step: (letter.charCodeAt(0) + 3) % 7, | ||
alt: acc[0] === "b" ? -acc.length : acc.length, | ||
oct: octStr.length ? +octStr : null, | ||
chroma: 0, | ||
midi: null, | ||
freq: null | ||
}; | ||
p.chroma = (SEMI[p.step] + p.alt + 120) % 12; | ||
p.midi = p.oct !== null ? SEMI[p.step] + p.alt + 12 * (p.oct + 1) : null; | ||
p.freq = midiToFreq(p.midi); | ||
return Object.freeze(p); | ||
}; | ||
var memo = function (fn, cache) { | ||
if ( cache === void 0 ) cache = {}; | ||
return function (str) { return cache[str] || (cache[str] = fn(str)); }; | ||
if (cache === void 0) { cache = {}; } | ||
return function (str) { return cache[str] || (cache[str] = fn(str)); }; | ||
}; | ||
/** | ||
* Get note properties. It returns an object with the following information: | ||
* | ||
* - name {String}: the note name. The letter is always in uppercase | ||
* - letter {String}: the note letter, always in uppercase | ||
* - acc {String}: the note accidentals | ||
* - octave {Number}: the octave or null if not present | ||
* - pc {String}: the pitch class (letter + accidentals) | ||
* - step {Number}: number equivalent of the note letter. 0 means C ... 6 means B. | ||
* - alt {Number}: number equivalent of accidentals (negative are flats, positive sharps) | ||
* - chroma {Number}: number equivalent of the pitch class, where 0 is C, 1 is C# or Db, 2 is D... | ||
* - midi {Number}: the note midi number (IMPORTANT! it can be outside 0 to 127 range) | ||
* - freq {Number}: the frequency using an equal temperament at 440Hz | ||
* | ||
* This function *always* returns an object with all this properties, but if it"s | ||
* not a valid note all properties will be null. | ||
* | ||
* The returned object can"t be mutated. | ||
* | ||
* @param {String} note - the note name in scientific notation | ||
* @return {Object} an object with the properties (or an object will all properties | ||
* set to null if not valid note) | ||
* @example | ||
* Note.props("fx-3").name // => "F##-3" | ||
* Note.props("invalid").name // => null | ||
* Note.props("C#3").oct // => 3 | ||
* Note.props().oct // => null | ||
*/ | ||
var props = memo(properties); | ||
/** | ||
* Given a note name, return the note name or null if not valid note. | ||
* The note name will ALWAYS have the letter in upercase and accidentals | ||
* using # or b | ||
* | ||
* Can be used to test if a string is a valid note name. | ||
* | ||
* @function | ||
* @param {Pitch|string} | ||
* @return {string} | ||
* | ||
* @example | ||
* Note.name("cb2") // => "Cb2" | ||
* ["c", "db3", "2", "g+", "gx4"].map(Note.name) // => ["C", "Db3", null, null, "G##4"] | ||
*/ | ||
var name = function (str) { return props(str).name; }; | ||
/** | ||
* Get pitch class of a note. The note can be a string or a pitch array. | ||
* | ||
* @function | ||
* @param {string|Pitch} | ||
* @return {string} the pitch class | ||
* @example | ||
* Note.pc("Db3") // => "Db" | ||
* ["db3", "bb6", "fx2"].map(Note.pc) // => [ "Db", "Bb", "F##"] | ||
*/ | ||
var pc = function (str) { return props(str).pc; }; | ||
var isMidiRange = function (m) { return m >= 0 && m <= 127; }; | ||
/** | ||
* Get the note midi number. It always return a number between 0 and 127 | ||
* | ||
* @function | ||
* @param {string|Number} note - the note to get the midi number from | ||
* @return {Integer} the midi number or null if not valid pitch | ||
* @example | ||
* Note.midi("C4") // => 60 | ||
* Note.midi(60) // => 60 | ||
* @see midi.toMidi | ||
*/ | ||
var midi = function (note) { | ||
if (typeof note !== "number" && typeof note !== "string") { | ||
return null; | ||
} | ||
var midi = props(note).midi; | ||
var value = midi || midi === 0 ? midi : +note; | ||
return isMidiRange(value) ? value : null; | ||
if (typeof note !== "number" && typeof note !== "string") { | ||
return null; | ||
} | ||
var midi = props(note).midi; | ||
var value = midi || midi === 0 ? midi : +note; | ||
return isMidiRange(value) ? value : null; | ||
}; | ||
/** | ||
* Get the frequency from midi number | ||
* | ||
* @param {Number} midi - the note midi number | ||
* @param {Number} tuning - (Optional) 440 by default | ||
* @return {Number} the frequency or null if not valid note midi | ||
*/ | ||
var midiToFreq = function (midi, tuning) { | ||
if ( tuning === void 0 ) tuning = 440; | ||
if (tuning === void 0) { tuning = 440; } | ||
return typeof midi === "number" ? Math.pow(2, (midi - 69) / 12) * tuning : null; | ||
}; | ||
/** | ||
* Get the frequency of a note | ||
* | ||
* @function | ||
* @param {string|Number} note - the note name or midi note number | ||
* @return {Number} the frequency | ||
* @example | ||
* Note.freq("A4") // => 440 | ||
* Note.freq(69) // => 440 | ||
*/ | ||
var freq = function (note) { return props(note).freq || midiToFreq(note); }; | ||
var L2 = Math.log(2); | ||
var L440 = Math.log(440); | ||
/** | ||
* Get the midi number from a frequency in hertz. The midi number can | ||
* contain decimals (with two digits precission) | ||
* | ||
* @param {Number} frequency | ||
* @return {Number} | ||
* @example | ||
* Note.freqToMidi(220)); //=> 57; | ||
* Note.freqToMidi(261.62)); //=> 60; | ||
* Note.freqToMidi(261)); //=> 59.96; | ||
*/ | ||
var freqToMidi = function (freq) { | ||
var v = (12 * (Math.log(freq) - L440)) / L2 + 69; | ||
return Math.round(v * 100) / 100; | ||
var v = (12 * (Math.log(freq) - L440)) / L2 + 69; | ||
return Math.round(v * 100) / 100; | ||
}; | ||
/** | ||
* Return the chroma of a note. The chroma is the numeric equivalent to the | ||
* pitch class, where 0 is C, 1 is C# or Db, 2 is D... 11 is B | ||
* | ||
* @param {string} note - the note name | ||
* @return {Integer} the chroma number | ||
* @example | ||
* Note.chroma("Cb") // => 11 | ||
* ["C", "D", "E", "F"].map(Note.chroma) // => [0, 2, 4, 5] | ||
*/ | ||
var chroma = function (str) { return props(str).chroma; }; | ||
/** | ||
* Get the octave of the given pitch | ||
* | ||
* @function | ||
* @param {string} note - the note | ||
* @return {Integer} the octave or null if doesn"t have an octave or not a valid note | ||
* @example | ||
* Note.oct("C#4") // => 4 | ||
* Note.oct("C") // => null | ||
* Note.oct("blah") // => undefined | ||
*/ | ||
var oct = function (str) { return props(str).oct; }; | ||
var LETTERS = "CDEFGAB"; | ||
/** | ||
* Given a step number return it's letter (0 = C, 1 = D, 2 = E) | ||
* @param {number} step | ||
* @return {string} the letter | ||
* @example | ||
* Note.stepToLetter(3) // => "F" | ||
*/ | ||
var stepToLetter = function (step) { return LETTERS[step]; }; | ||
var fillStr = function (s, n) { return Array(n + 1).join(s); }; | ||
var numToStr = function (num, op) { return (typeof num !== "number" ? "" : op(num)); }; | ||
/** | ||
* Given an alteration number, return the accidentals | ||
* @param {Number} alt | ||
* @return {String} | ||
* @example | ||
* Note.altToAcc(-3) // => "bbb" | ||
*/ | ||
var altToAcc = function (alt) { return numToStr(alt, function (alt) { return (alt < 0 ? fillStr("b", -alt) : fillStr("#", alt)); }); }; | ||
/** | ||
* Creates a note name in scientific notation from note properties, | ||
* and optionally another note name. | ||
* It receives an object with: | ||
* - step: the note step (0 = C, 1 = D, ... 6 = B) | ||
* - alt: (optional) the alteration. Negative numbers are flats, positive sharps | ||
* - oct: (optional) the octave | ||
* | ||
* Optionally it receives another note as a "base", meaning that any prop not explicitly | ||
* received on the first parameter will be taken from that base note. That way it can be used | ||
* as an immutable "set" operator for a that base note | ||
* | ||
* @function | ||
* @param {Object} props - the note properties | ||
* @param {String} [baseNote] - note to build the result from. If given, it returns | ||
* the result of applying the given props to this note. | ||
* @return {String} the note name in scientific notation or null if not valid properties | ||
* @example | ||
* Note.from({ step: 5 }) // => "A" | ||
* Note.from({ step: 1, acc: -1 }) // => "Db" | ||
* Note.from({ step: 2, acc: 2, oct: 2 }) // => "E##2" | ||
* Note.from({ step: 7 }) // => null | ||
* Note.from({alt: 1, oct: 3}, "C4") // => "C#3" | ||
*/ | ||
var numToStr = function (num, op) { | ||
return typeof num !== "number" ? "" : op(num); | ||
}; | ||
var altToAcc = function (alt) { | ||
return numToStr(alt, function (alt) { return (alt < 0 ? fillStr("b", -alt) : fillStr("#", alt)); }); | ||
}; | ||
var from = function (fromProps, baseNote) { | ||
if ( fromProps === void 0 ) fromProps = {}; | ||
if ( baseNote === void 0 ) baseNote = null; | ||
var ref = baseNote | ||
? Object.assign({}, props(baseNote), fromProps) | ||
: fromProps; | ||
var step = ref.step; | ||
var alt = ref.alt; | ||
var oct = ref.oct; | ||
var letter = stepToLetter(step); | ||
if (!letter) { return null; } | ||
var pc = letter + altToAcc(alt); | ||
return oct || oct === 0 ? pc + oct : pc; | ||
if (fromProps === void 0) { fromProps = {}; } | ||
if (baseNote === void 0) { baseNote = null; } | ||
var _a = baseNote | ||
? Object.assign({}, props(baseNote), fromProps) | ||
: fromProps, step = _a.step, alt = _a.alt, oct = _a.oct; | ||
if (typeof step !== "number") | ||
return null; | ||
var letter = stepToLetter(step); | ||
if (!letter) | ||
return null; | ||
var pc = letter + altToAcc(alt); | ||
return oct || oct === 0 ? pc + oct : pc; | ||
}; | ||
/** | ||
* Deprecated. This is kept for backwards compatibility only. | ||
* Use Note.from instead | ||
*/ | ||
var build = from; | ||
/** | ||
* Given a midi number, returns a note name. The altered notes will have | ||
* flats unless explicitly set with the optional `useSharps` parameter. | ||
* | ||
* @function | ||
* @param {number} midi - the midi note number | ||
* @param {boolean} useSharps - (Optional) set to true to use sharps instead of flats | ||
* @return {string} the note name | ||
* @example | ||
* Note.fromMidi(61) // => "Db4" | ||
* Note.fromMidi(61, true) // => "C#4" | ||
* // it rounds to nearest note | ||
* Note.fromMidi(61.7) // => "D4" | ||
*/ | ||
function fromMidi(num, sharps) { | ||
num = Math.round(num); | ||
var pcs = sharps === true ? SHARPS : FLATS; | ||
var pc = pcs[num % 12]; | ||
var o = Math.floor(num / 12) - 1; | ||
return pc + o; | ||
if (sharps === void 0) { sharps = false; } | ||
num = Math.round(num); | ||
var pcs = sharps === true ? SHARPS : FLATS; | ||
var pc = pcs[num % 12]; | ||
var o = Math.floor(num / 12) - 1; | ||
return pc + o; | ||
} | ||
/** | ||
* Simplify the note: find an enhramonic note with less accidentals. | ||
* | ||
* @param {String} note - the note to be simplified | ||
* @param {boolean} useSameAccType - (optional, true by default) set to true | ||
* to ensure the returned note has the same accidental types that the given note | ||
* @return {String} the simplfiied note or null if not valid note | ||
* @example | ||
* Note.simplify("C##") // => "D" | ||
* Note.simplify("C###") // => "D#" | ||
* Note.simplify("C###", false) // => "Eb" | ||
* Note.simplify("B#4") // => "C5" | ||
*/ | ||
var simplify = function (note, sameAcc) { | ||
var ref = props(note); | ||
var alt = ref.alt; | ||
var chroma = ref.chroma; | ||
var midi = ref.midi; | ||
if (chroma === null) { return null; } | ||
var useSharps = sameAcc === false ? alt < 0 : alt > 0; | ||
return midi === null | ||
? pc(fromMidi(chroma, useSharps)) | ||
: fromMidi(midi, useSharps); | ||
if (sameAcc === void 0) { sameAcc = true; } | ||
var _a = props(note), alt = _a.alt, chroma = _a.chroma, midi = _a.midi; | ||
if (chroma === null) | ||
return null; | ||
var alteration = alt; | ||
var useSharps = sameAcc === false ? alteration < 0 : alteration > 0; | ||
return midi === null | ||
? pc(fromMidi(chroma, useSharps)) | ||
: fromMidi(midi, useSharps); | ||
}; | ||
/** | ||
* Get the simplified and enhramonic note of the given one. | ||
* | ||
* @param {String} note | ||
* @return {String} the enhramonic note | ||
* @example | ||
* Note.enharmonic("Db") // => "C#" | ||
* Note.enhramonic("C") // => "C" | ||
*/ | ||
var enharmonic = function (note) { return simplify(note, false); }; | ||
@@ -396,0 +132,0 @@ |
468
build/es6.js
@@ -1,390 +0,128 @@ | ||
/** | ||
* [![npm version](https://img.shields.io/npm/v/tonal-note.svg)](https://www.npmjs.com/package/tonal-note) | ||
* [![tonal](https://img.shields.io/badge/tonal-note-yellow.svg)](https://www.npmjs.com/browse/keyword/tonal) | ||
* | ||
* `tonal-note` is a collection of functions to manipulate musical notes in scientific notation | ||
* | ||
* This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library. | ||
* | ||
* ## Usage | ||
* | ||
* ```js | ||
* import * as Note from "tonal-note" | ||
* // or const Note = require("tonal-note") | ||
* Note.name("bb2") // => "Bb2" | ||
* Note.chroma("bb2") // => 10 | ||
* Note.midi("a4") // => 69 | ||
* Note.freq("a4") // => 440 | ||
* Note.oct("G3") // => 3 | ||
* | ||
* // part of tonal | ||
* const Tonal = require("tonal") | ||
* // or import Note from "tonal" | ||
* Tonal.Note.midi("d4") // => 62 | ||
* ``` | ||
* | ||
* ## Install | ||
* | ||
* [![npm install tonal-note](https://nodei.co/npm/tonal-note.png?mini=true)](https://npmjs.org/package/tonal-note/) | ||
* | ||
* ## API Documentation | ||
* | ||
* @module Note | ||
*/ | ||
var NAMES = "C C# Db D D# Eb E F F# Gb G G# Ab A A# Bb B".split(" "); | ||
/** | ||
* Get a list of note names (pitch classes) within a octave | ||
* | ||
* @param {string} accTypes - (Optional, by default " b#"). A string with the | ||
* accidentals types: " " means no accidental, "#" means sharps, "b" mean flats, | ||
* can be combined (see examples) | ||
* @return {Array} | ||
* @example | ||
* Note.names(" b") // => [ "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" ] | ||
* Note.names(" #") // => [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ] | ||
*/ | ||
export var names = function (accTypes) { return typeof accTypes !== "string" | ||
? NAMES.slice() | ||
: NAMES.filter(function (n) { | ||
var acc = n[1] || " "; | ||
return accTypes.indexOf(acc) !== -1; | ||
}); }; | ||
var names = function (accTypes) { | ||
return typeof accTypes !== "string" | ||
? NAMES.slice() | ||
: NAMES.filter(function (n) { | ||
var acc = n[1] || " "; | ||
return accTypes.indexOf(acc) !== -1; | ||
}); | ||
}; | ||
var SHARPS = names(" #"); | ||
var FLATS = names(" b"); | ||
var REGEX = /^([a-gA-G]?)(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)$/; | ||
/** | ||
* Split a string into tokens related to note parts. | ||
* It returns an array of strings `[letter, accidental, octave, modifier]` | ||
* | ||
* It always returns an array | ||
* | ||
* @param {String} str | ||
* @return {Array} an array of note tokens | ||
* @example | ||
* Note.tokenize("C#2") // => ["C", "#", "2", ""] | ||
* Note.tokenize("Db3 major") // => ["D", "b", "3", "major"] | ||
* Note.tokenize("major") // => ["", "", "", "major"] | ||
* Note.tokenize("##") // => ["", "##", "", ""] | ||
* Note.tokenize() // => ["", "", "", ""] | ||
*/ | ||
export function tokenize(str) { | ||
if (typeof str !== "string") { str = ""; } | ||
var m = REGEX.exec(str); | ||
if (!m) { return null; } | ||
return [m[1].toUpperCase(), m[2].replace(/x/g, "##"), m[3], m[4]]; | ||
function tokenize(str) { | ||
if (typeof str !== "string") | ||
str = ""; | ||
var m = REGEX.exec(str); | ||
return [m[1].toUpperCase(), m[2].replace(/x/g, "##"), m[3], m[4]]; | ||
} | ||
var NO_NOTE = Object.freeze({ | ||
pc: null, | ||
name: null, | ||
step: null, | ||
alt: null, | ||
oct: null, | ||
octStr: null, | ||
chroma: null, | ||
midi: null, | ||
freq: null | ||
pc: null, | ||
name: null, | ||
step: null, | ||
alt: null, | ||
oct: null, | ||
octStr: null, | ||
chroma: null, | ||
midi: null, | ||
freq: null | ||
}); | ||
var SEMI = [0, 2, 4, 5, 7, 9, 11]; | ||
var properties = function (str) { | ||
var tokens = tokenize(str); | ||
if (tokens[0] === "" || tokens[3] !== "") { return NO_NOTE; } | ||
var letter = tokens[0]; | ||
var acc = tokens[1]; | ||
var octStr = tokens[2]; | ||
var p = { letter: letter, acc: acc, octStr: octStr }; | ||
p.pc = p.letter + p.acc; | ||
p.name = p.pc + octStr; | ||
p.step = (p.letter.charCodeAt(0) + 3) % 7; | ||
p.alt = p.acc[0] === "b" ? -p.acc.length : p.acc.length; | ||
p.oct = octStr.length ? +octStr : null; | ||
p.chroma = (SEMI[p.step] + p.alt + 120) % 12; | ||
p.midi = p.oct !== null ? SEMI[p.step] + p.alt + 12 * (p.oct + 1) : null; | ||
p.freq = midiToFreq(p.midi); | ||
return Object.freeze(p); | ||
var tokens = tokenize(str); | ||
if (tokens[0] === "" || tokens[3] !== "") | ||
return NO_NOTE; | ||
var letter = tokens[0], acc = tokens[1], octStr = tokens[2]; | ||
var p = { | ||
letter: letter, | ||
acc: acc, | ||
octStr: octStr, | ||
pc: letter + acc, | ||
name: letter + acc + octStr, | ||
step: (letter.charCodeAt(0) + 3) % 7, | ||
alt: acc[0] === "b" ? -acc.length : acc.length, | ||
oct: octStr.length ? +octStr : null, | ||
chroma: 0, | ||
midi: null, | ||
freq: null | ||
}; | ||
p.chroma = (SEMI[p.step] + p.alt + 120) % 12; | ||
p.midi = p.oct !== null ? SEMI[p.step] + p.alt + 12 * (p.oct + 1) : null; | ||
p.freq = midiToFreq(p.midi); | ||
return Object.freeze(p); | ||
}; | ||
var memo = function (fn, cache) { | ||
if ( cache === void 0 ) cache = {}; | ||
return function (str) { return cache[str] || (cache[str] = fn(str)); }; | ||
if (cache === void 0) { cache = {}; } | ||
return function (str) { return cache[str] || (cache[str] = fn(str)); }; | ||
}; | ||
/** | ||
* Get note properties. It returns an object with the following information: | ||
* | ||
* - name {String}: the note name. The letter is always in uppercase | ||
* - letter {String}: the note letter, always in uppercase | ||
* - acc {String}: the note accidentals | ||
* - octave {Number}: the octave or null if not present | ||
* - pc {String}: the pitch class (letter + accidentals) | ||
* - step {Number}: number equivalent of the note letter. 0 means C ... 6 means B. | ||
* - alt {Number}: number equivalent of accidentals (negative are flats, positive sharps) | ||
* - chroma {Number}: number equivalent of the pitch class, where 0 is C, 1 is C# or Db, 2 is D... | ||
* - midi {Number}: the note midi number (IMPORTANT! it can be outside 0 to 127 range) | ||
* - freq {Number}: the frequency using an equal temperament at 440Hz | ||
* | ||
* This function *always* returns an object with all this properties, but if it"s | ||
* not a valid note all properties will be null. | ||
* | ||
* The returned object can"t be mutated. | ||
* | ||
* @param {String} note - the note name in scientific notation | ||
* @return {Object} an object with the properties (or an object will all properties | ||
* set to null if not valid note) | ||
* @example | ||
* Note.props("fx-3").name // => "F##-3" | ||
* Note.props("invalid").name // => null | ||
* Note.props("C#3").oct // => 3 | ||
* Note.props().oct // => null | ||
*/ | ||
export var props = memo(properties); | ||
/** | ||
* Given a note name, return the note name or null if not valid note. | ||
* The note name will ALWAYS have the letter in upercase and accidentals | ||
* using # or b | ||
* | ||
* Can be used to test if a string is a valid note name. | ||
* | ||
* @function | ||
* @param {Pitch|string} | ||
* @return {string} | ||
* | ||
* @example | ||
* Note.name("cb2") // => "Cb2" | ||
* ["c", "db3", "2", "g+", "gx4"].map(Note.name) // => ["C", "Db3", null, null, "G##4"] | ||
*/ | ||
export var name = function (str) { return props(str).name; }; | ||
/** | ||
* Get pitch class of a note. The note can be a string or a pitch array. | ||
* | ||
* @function | ||
* @param {string|Pitch} | ||
* @return {string} the pitch class | ||
* @example | ||
* Note.pc("Db3") // => "Db" | ||
* ["db3", "bb6", "fx2"].map(Note.pc) // => [ "Db", "Bb", "F##"] | ||
*/ | ||
export var pc = function (str) { return props(str).pc; }; | ||
var props = memo(properties); | ||
var name = function (str) { return props(str).name; }; | ||
var pc = function (str) { return props(str).pc; }; | ||
var isMidiRange = function (m) { return m >= 0 && m <= 127; }; | ||
/** | ||
* Get the note midi number. It always return a number between 0 and 127 | ||
* | ||
* @function | ||
* @param {string|Number} note - the note to get the midi number from | ||
* @return {Integer} the midi number or null if not valid pitch | ||
* @example | ||
* Note.midi("C4") // => 60 | ||
* Note.midi(60) // => 60 | ||
* @see midi.toMidi | ||
*/ | ||
export var midi = function (note) { | ||
if (typeof note !== "number" && typeof note !== "string") { | ||
return null; | ||
} | ||
var midi = props(note).midi; | ||
var value = midi || midi === 0 ? midi : +note; | ||
return isMidiRange(value) ? value : null; | ||
var midi = function (note) { | ||
if (typeof note !== "number" && typeof note !== "string") { | ||
return null; | ||
} | ||
var midi = props(note).midi; | ||
var value = midi || midi === 0 ? midi : +note; | ||
return isMidiRange(value) ? value : null; | ||
}; | ||
/** | ||
* Get the frequency from midi number | ||
* | ||
* @param {Number} midi - the note midi number | ||
* @param {Number} tuning - (Optional) 440 by default | ||
* @return {Number} the frequency or null if not valid note midi | ||
*/ | ||
export var midiToFreq = function (midi, tuning) { | ||
if ( tuning === void 0 ) tuning = 440; | ||
var midiToFreq = function (midi, tuning) { | ||
if (tuning === void 0) { tuning = 440; } | ||
return typeof midi === "number" ? Math.pow(2, (midi - 69) / 12) * tuning : null; | ||
}; | ||
/** | ||
* Get the frequency of a note | ||
* | ||
* @function | ||
* @param {string|Number} note - the note name or midi note number | ||
* @return {Number} the frequency | ||
* @example | ||
* Note.freq("A4") // => 440 | ||
* Note.freq(69) // => 440 | ||
*/ | ||
export var freq = function (note) { return props(note).freq || midiToFreq(note); }; | ||
var freq = function (note) { return props(note).freq || midiToFreq(note); }; | ||
var L2 = Math.log(2); | ||
var L440 = Math.log(440); | ||
/** | ||
* Get the midi number from a frequency in hertz. The midi number can | ||
* contain decimals (with two digits precission) | ||
* | ||
* @param {Number} frequency | ||
* @return {Number} | ||
* @example | ||
* Note.freqToMidi(220)); //=> 57; | ||
* Note.freqToMidi(261.62)); //=> 60; | ||
* Note.freqToMidi(261)); //=> 59.96; | ||
*/ | ||
export var freqToMidi = function (freq) { | ||
var v = (12 * (Math.log(freq) - L440)) / L2 + 69; | ||
return Math.round(v * 100) / 100; | ||
var freqToMidi = function (freq) { | ||
var v = (12 * (Math.log(freq) - L440)) / L2 + 69; | ||
return Math.round(v * 100) / 100; | ||
}; | ||
/** | ||
* Return the chroma of a note. The chroma is the numeric equivalent to the | ||
* pitch class, where 0 is C, 1 is C# or Db, 2 is D... 11 is B | ||
* | ||
* @param {string} note - the note name | ||
* @return {Integer} the chroma number | ||
* @example | ||
* Note.chroma("Cb") // => 11 | ||
* ["C", "D", "E", "F"].map(Note.chroma) // => [0, 2, 4, 5] | ||
*/ | ||
export var chroma = function (str) { return props(str).chroma; }; | ||
/** | ||
* Get the octave of the given pitch | ||
* | ||
* @function | ||
* @param {string} note - the note | ||
* @return {Integer} the octave or null if doesn"t have an octave or not a valid note | ||
* @example | ||
* Note.oct("C#4") // => 4 | ||
* Note.oct("C") // => null | ||
* Note.oct("blah") // => undefined | ||
*/ | ||
export var oct = function (str) { return props(str).oct; }; | ||
var chroma = function (str) { return props(str).chroma; }; | ||
var oct = function (str) { return props(str).oct; }; | ||
var LETTERS = "CDEFGAB"; | ||
/** | ||
* Given a step number return it's letter (0 = C, 1 = D, 2 = E) | ||
* @param {number} step | ||
* @return {string} the letter | ||
* @example | ||
* Note.stepToLetter(3) // => "F" | ||
*/ | ||
export var stepToLetter = function (step) { return LETTERS[step]; }; | ||
var stepToLetter = function (step) { return LETTERS[step]; }; | ||
var fillStr = function (s, n) { return Array(n + 1).join(s); }; | ||
var numToStr = function (num, op) { return (typeof num !== "number" ? "" : op(num)); }; | ||
/** | ||
* Given an alteration number, return the accidentals | ||
* @param {Number} alt | ||
* @return {String} | ||
* @example | ||
* Note.altToAcc(-3) // => "bbb" | ||
*/ | ||
export var altToAcc = function (alt) { return numToStr(alt, function (alt) { return (alt < 0 ? fillStr("b", -alt) : fillStr("#", alt)); }); }; | ||
/** | ||
* Creates a note name in scientific notation from note properties, | ||
* and optionally another note name. | ||
* It receives an object with: | ||
* - step: the note step (0 = C, 1 = D, ... 6 = B) | ||
* - alt: (optional) the alteration. Negative numbers are flats, positive sharps | ||
* - oct: (optional) the octave | ||
* | ||
* Optionally it receives another note as a "base", meaning that any prop not explicitly | ||
* received on the first parameter will be taken from that base note. That way it can be used | ||
* as an immutable "set" operator for a that base note | ||
* | ||
* @function | ||
* @param {Object} props - the note properties | ||
* @param {String} [baseNote] - note to build the result from. If given, it returns | ||
* the result of applying the given props to this note. | ||
* @return {String} the note name in scientific notation or null if not valid properties | ||
* @example | ||
* Note.from({ step: 5 }) // => "A" | ||
* Note.from({ step: 1, acc: -1 }) // => "Db" | ||
* Note.from({ step: 2, acc: 2, oct: 2 }) // => "E##2" | ||
* Note.from({ step: 7 }) // => null | ||
* Note.from({alt: 1, oct: 3}, "C4") // => "C#3" | ||
*/ | ||
export var from = function (fromProps, baseNote) { | ||
if ( fromProps === void 0 ) fromProps = {}; | ||
if ( baseNote === void 0 ) baseNote = null; | ||
var ref = baseNote | ||
? Object.assign({}, props(baseNote), fromProps) | ||
: fromProps; | ||
var step = ref.step; | ||
var alt = ref.alt; | ||
var oct = ref.oct; | ||
var letter = stepToLetter(step); | ||
if (!letter) { return null; } | ||
var pc = letter + altToAcc(alt); | ||
return oct || oct === 0 ? pc + oct : pc; | ||
var numToStr = function (num, op) { | ||
return typeof num !== "number" ? "" : op(num); | ||
}; | ||
/** | ||
* Deprecated. This is kept for backwards compatibility only. | ||
* Use Note.from instead | ||
*/ | ||
export var build = from; | ||
/** | ||
* Given a midi number, returns a note name. The altered notes will have | ||
* flats unless explicitly set with the optional `useSharps` parameter. | ||
* | ||
* @function | ||
* @param {number} midi - the midi note number | ||
* @param {boolean} useSharps - (Optional) set to true to use sharps instead of flats | ||
* @return {string} the note name | ||
* @example | ||
* Note.fromMidi(61) // => "Db4" | ||
* Note.fromMidi(61, true) // => "C#4" | ||
* // it rounds to nearest note | ||
* Note.fromMidi(61.7) // => "D4" | ||
*/ | ||
export function fromMidi(num, sharps) { | ||
num = Math.round(num); | ||
var pcs = sharps === true ? SHARPS : FLATS; | ||
var pc = pcs[num % 12]; | ||
var o = Math.floor(num / 12) - 1; | ||
return pc + o; | ||
var altToAcc = function (alt) { | ||
return numToStr(alt, function (alt) { return (alt < 0 ? fillStr("b", -alt) : fillStr("#", alt)); }); | ||
}; | ||
var from = function (fromProps, baseNote) { | ||
if (fromProps === void 0) { fromProps = {}; } | ||
if (baseNote === void 0) { baseNote = null; } | ||
var _a = baseNote | ||
? Object.assign({}, props(baseNote), fromProps) | ||
: fromProps, step = _a.step, alt = _a.alt, oct = _a.oct; | ||
if (typeof step !== "number") | ||
return null; | ||
var letter = stepToLetter(step); | ||
if (!letter) | ||
return null; | ||
var pc = letter + altToAcc(alt); | ||
return oct || oct === 0 ? pc + oct : pc; | ||
}; | ||
var build = from; | ||
function fromMidi(num, sharps) { | ||
if (sharps === void 0) { sharps = false; } | ||
num = Math.round(num); | ||
var pcs = sharps === true ? SHARPS : FLATS; | ||
var pc = pcs[num % 12]; | ||
var o = Math.floor(num / 12) - 1; | ||
return pc + o; | ||
} | ||
/** | ||
* Simplify the note: find an enhramonic note with less accidentals. | ||
* | ||
* @param {String} note - the note to be simplified | ||
* @param {boolean} useSameAccType - (optional, true by default) set to true | ||
* to ensure the returned note has the same accidental types that the given note | ||
* @return {String} the simplfiied note or null if not valid note | ||
* @example | ||
* Note.simplify("C##") // => "D" | ||
* Note.simplify("C###") // => "D#" | ||
* Note.simplify("C###", false) // => "Eb" | ||
* Note.simplify("B#4") // => "C5" | ||
*/ | ||
export var simplify = function (note, sameAcc) { | ||
var ref = props(note); | ||
var alt = ref.alt; | ||
var chroma = ref.chroma; | ||
var midi = ref.midi; | ||
if (chroma === null) { return null; } | ||
var useSharps = sameAcc === false ? alt < 0 : alt > 0; | ||
return midi === null | ||
? pc(fromMidi(chroma, useSharps)) | ||
: fromMidi(midi, useSharps); | ||
var simplify = function (note, sameAcc) { | ||
if (sameAcc === void 0) { sameAcc = true; } | ||
var _a = props(note), alt = _a.alt, chroma = _a.chroma, midi = _a.midi; | ||
if (chroma === null) | ||
return null; | ||
var alteration = alt; | ||
var useSharps = sameAcc === false ? alteration < 0 : alteration > 0; | ||
return midi === null | ||
? pc(fromMidi(chroma, useSharps)) | ||
: fromMidi(midi, useSharps); | ||
}; | ||
var enharmonic = function (note) { return simplify(note, false); }; | ||
/** | ||
* Get the simplified and enhramonic note of the given one. | ||
* | ||
* @param {String} note | ||
* @return {String} the enhramonic note | ||
* @example | ||
* Note.enharmonic("Db") // => "C#" | ||
* Note.enhramonic("C") // => "C" | ||
*/ | ||
export var enharmonic = function (note) { return simplify(note, false); }; | ||
export { names, tokenize, props, name, pc, midi, midiToFreq, freq, freqToMidi, chroma, oct, stepToLetter, altToAcc, from, build, fromMidi, simplify, enharmonic }; |
{ | ||
"name": "tonal-note", | ||
"version": "2.1.0", | ||
"version": "2.1.2", | ||
"repository": "https://github.com/danigb/tonal/packages/note", | ||
@@ -13,15 +13,18 @@ "description": "Parse and manipulate music notes in scientific notation", | ||
"scripts": { | ||
"docs": "jsdoc2md -d 1 --name-format --member-index-format list index.js > README.md", | ||
"test": "jest --coverage" | ||
"docs": "jsdoc2md --files 'index.ts' --configure ../../config/jsdoc2md.json > README.md", | ||
"test": "jest --coverage", | ||
"build": "rollup -c ../../config/rollup.config.ts.js index.ts" | ||
}, | ||
"main": "build/es5.js", | ||
"module": "build/es6.js", | ||
"types": "build/index.d.ts", | ||
"jsnext:main": "index", | ||
"author": "danigb", | ||
"license": "MIT", | ||
"babel": { | ||
"presets": [ | ||
"es2015" | ||
] | ||
"jest": { | ||
"preset": "ts-jest" | ||
}, | ||
"devDependencies": { | ||
"jsdoc-babel": "^0.5.0" | ||
} | ||
} |
586
README.md
<a name="module_Note"></a> | ||
# Note | ||
[![npm version](https://img.shields.io/npm/v/tonal-note.svg)](https://www.npmjs.com/package/tonal-note) | ||
[![tonal](https://img.shields.io/badge/tonal-note-yellow.svg)](https://www.npmjs.com/browse/keyword/tonal) | ||
## Note | ||
`tonal-note` is a collection of functions to manipulate musical notes in scientific notation | ||
<p><a href="https://www.npmjs.com/package/tonal-note"><img src="https://img.shields.io/npm/v/tonal-note.svg" alt="npm version"></a> | ||
<a href="https://www.npmjs.com/browse/keyword/tonal"><img src="https://img.shields.io/badge/tonal-note-yellow.svg" alt="tonal"></a></p> | ||
<p><code>tonal-note</code> is a collection of functions to manipulate musical notes in scientific notation</p> | ||
<p>This is part of <a href="https://www.npmjs.com/package/tonal">tonal</a> music theory library.</p> | ||
<h2>Usage</h2><pre class="prettyprint source lang-js"><code>import * as Note from "tonal-note" | ||
// or const Note = require("tonal-note") | ||
Note.name("bb2") // => "Bb2" | ||
Note.chroma("bb2") // => 10 | ||
Note.midi("a4") // => 69 | ||
Note.freq("a4") // => 440 | ||
Note.oct("G3") // => 3 | ||
This is part of [tonal](https://www.npmjs.com/package/tonal) music theory library. | ||
// part of tonal | ||
const Tonal = require("tonal") | ||
// or import Note from "tonal" | ||
Tonal.Note.midi("d4") // => 62</code></pre><h2>Install</h2><p><a href="https://npmjs.org/package/tonal-note/"><img src="https://nodei.co/npm/tonal-note.png?mini=true" alt="npm install tonal-note"></a></p> | ||
## Usage | ||
<h2>API Documentation</h2> | ||
- [Note](#module_Note) | ||
- _static_ | ||
- [.midi](#module_Note.midi) ⇒ <code>Number</code> | ||
- [.freqToMidi](#module_Note.freqToMidi) ⇒ <code>Integer</code> | ||
- [.from](#module_Note.from) | ||
- [.simplify](#module_Note.simplify) ⇒ <code>String</code> | ||
- [.props()](#module_Note.props) ⇒ <code>string</code> | ||
- [.name()](#module_Note.name) ⇒ <code>string</code> | ||
- [.midiToFreq(note)](#module_Note.midiToFreq) ⇒ <code>Number</code> | ||
- [.chroma(note)](#module_Note.chroma) ⇒ <code>Integer</code> | ||
- [.altToAcc(props, [baseNote])](#module_Note.altToAcc) ⇒ <code>String</code> | ||
- [.build(midi, useSharps)](#module_Note.build) ⇒ <code>string</code> | ||
- _inner_ | ||
- [~props](#module_Note..props) ⇒ <code>Object</code> | ||
- [~names(accTypes)](#module_Note..names) ⇒ <code>Array</code> | ||
- [~tokenize(str)](#module_Note..tokenize) ⇒ <code>Array</code> | ||
- [~midi(note)](#module_Note..midi) ⇒ <code>Integer</code> | ||
- [~freqToMidi(frequency)](#module_Note..freqToMidi) ⇒ <code>Number</code> | ||
- [~stepToLetter(step)](#module_Note..stepToLetter) ⇒ <code>string</code> | ||
- [~altToAcc(alt)](#module_Note..altToAcc) ⇒ <code>String</code> | ||
- [~simplify(note, useSameAccType)](#module_Note..simplify) ⇒ <code>String</code> | ||
<a name="module_Note.midi"></a> | ||
### Note.midi ⇒ <code>Number</code> | ||
<p>Get the frequency from midi number</p> | ||
**Kind**: static property of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Number</code> - <p>the frequency or null if not valid note midi</p> | ||
| Param | Type | Description | | ||
| ------ | ------------------- | -------------------------------- | | ||
| midi | <code>Number</code> | <p>the note midi number</p> | | ||
| tuning | <code>Number</code> | <p>(Optional) 440 by default</p> | | ||
<a name="module_Note.freqToMidi"></a> | ||
### Note.freqToMidi ⇒ <code>Integer</code> | ||
<p>Return the chroma of a note. The chroma is the numeric equivalent to the | ||
pitch class, where 0 is C, 1 is C# or Db, 2 is D... 11 is B</p> | ||
**Kind**: static property of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - <p>the chroma number</p> | ||
| Param | Type | Description | | ||
| ----- | ------------------- | -------------------- | | ||
| note | <code>string</code> | <p>the note name</p> | | ||
**Example** | ||
```js | ||
import * as Note from "tonal-note" | ||
// or const Note = require("tonal-note") | ||
Note.name("bb2") // => "Bb2" | ||
Note.chroma("bb2") // => 10 | ||
Note.midi("a4") // => 69 | ||
Note.freq("a4") // => 440 | ||
Note.oct("G3") // => 3 | ||
// part of tonal | ||
const Tonal = require("tonal") | ||
// or import Note from "tonal" | ||
Tonal.Note.midi("d4") // => 62 | ||
Note.chroma("Cb") // => 11 | ||
[("C", "D", "E", "F")].map(Note.chroma); // => [0, 2, 4, 5] | ||
``` | ||
## Install | ||
<a name="module_Note.from"></a> | ||
[![npm install tonal-note](https://nodei.co/npm/tonal-note.png?mini=true)](https://npmjs.org/package/tonal-note/) | ||
### Note.from | ||
## API Documentation | ||
<p>Deprecated. This is kept for backwards compatibility only. | ||
Use Note.from instead</p> | ||
**Kind**: static property of [<code>Note</code>](#module_Note) | ||
<a name="module_Note.simplify"></a> | ||
* [Note](#module_Note) | ||
* [`.names`](#module_Note.names) ⇒ <code>Array</code> | ||
* [`.props`](#module_Note.props) ⇒ <code>Object</code> | ||
* [`.midiToFreq`](#module_Note.midiToFreq) ⇒ <code>Number</code> | ||
* [`.freqToMidi`](#module_Note.freqToMidi) ⇒ <code>Number</code> | ||
* [`.chroma`](#module_Note.chroma) ⇒ <code>Integer</code> | ||
* [`.stepToLetter`](#module_Note.stepToLetter) ⇒ <code>string</code> | ||
* [`.altToAcc`](#module_Note.altToAcc) ⇒ <code>String</code> | ||
* [`.build`](#module_Note.build) | ||
* [`.simplify`](#module_Note.simplify) ⇒ <code>String</code> | ||
* [`.enharmonic`](#module_Note.enharmonic) ⇒ <code>String</code> | ||
* [`.tokenize(str)`](#module_Note.tokenize) ⇒ <code>Array</code> | ||
* [`.name()`](#module_Note.name) ⇒ <code>string</code> | ||
* [`.pc()`](#module_Note.pc) ⇒ <code>string</code> | ||
* [`.midi(note)`](#module_Note.midi) ⇒ <code>Integer</code> | ||
* [`.freq(note)`](#module_Note.freq) ⇒ <code>Number</code> | ||
* [`.oct(note)`](#module_Note.oct) ⇒ <code>Integer</code> | ||
* [`.from(props, [baseNote])`](#module_Note.from) ⇒ <code>String</code> | ||
* [`.fromMidi(midi, useSharps)`](#module_Note.fromMidi) ⇒ <code>string</code> | ||
### Note.simplify ⇒ <code>String</code> | ||
<a name="module_Note.names"></a> | ||
<p>Get the simplified and enhramonic note of the given one.</p> | ||
## `Note.names` ⇒ <code>Array</code> | ||
Get a list of note names (pitch classes) within a octave | ||
**Kind**: static property of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - <p>the enhramonic note</p> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
| Param | Type | | ||
| ----- | ------------------- | | ||
| note | <code>String</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| accTypes | <code>string</code> | (Optional, by default " b#"). A string with the accidentals types: " " means no accidental, "#" means sharps, "b" mean flats, can be combined (see examples) | | ||
**Example** | ||
**Example** | ||
```js | ||
Note.names(" b") // => [ "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" ] | ||
Note.names(" #") // => [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ] | ||
Note.enharmonic("Db"); // => "C#" | ||
Note.enhramonic("C"); // => "C" | ||
``` | ||
<a name="module_Note.props"></a> | ||
## `Note.props` ⇒ <code>Object</code> | ||
Get note properties. It returns an object with the following information: | ||
### Note.props() ⇒ <code>string</code> | ||
- name {String}: the note name. The letter is always in uppercase | ||
- letter {String}: the note letter, always in uppercase | ||
- acc {String}: the note accidentals | ||
- octave {Number}: the octave or null if not present | ||
- pc {String}: the pitch class (letter + accidentals) | ||
- step {Number}: number equivalent of the note letter. 0 means C ... 6 means B. | ||
- alt {Number}: number equivalent of accidentals (negative are flats, positive sharps) | ||
- chroma {Number}: number equivalent of the pitch class, where 0 is C, 1 is C# or Db, 2 is D... | ||
- midi {Number}: the note midi number (IMPORTANT! it can be outside 0 to 127 range) | ||
- freq {Number}: the frequency using an equal temperament at 440Hz | ||
<p>Given a note name, return the note name or null if not valid note. | ||
The note name will ALWAYS have the letter in upercase and accidentals | ||
using # or b</p> | ||
<p>Can be used to test if a string is a valid note name.</p> | ||
This function *always* returns an object with all this properties, but if it"s | ||
not a valid note all properties will be null. | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
The returned object can"t be mutated. | ||
| Param | Type | | ||
| ----- | ----------------------------------------- | | ||
| | <code>Pitch</code> \| <code>string</code> | | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Object</code> - an object with the properties (or an object will all properties | ||
set to null if not valid note) | ||
**Example** | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>String</code> | the note name in scientific notation | | ||
**Example** | ||
```js | ||
Note.props("fx-3").name // => "F##-3" | ||
Note.props("invalid").name // => null | ||
Note.props("C#3").oct // => 3 | ||
Note.props().oct // => null | ||
Note.name("cb2") // => "Cb2" | ||
[("c", "db3", "2", "g+", "gx4")].map(Note.name); // => ["C", "Db3", null, null, "G##4"] | ||
``` | ||
<a name="module_Note.midiToFreq"></a> | ||
## `Note.midiToFreq` ⇒ <code>Number</code> | ||
Get the frequency from midi number | ||
<a name="module_Note.name"></a> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Number</code> - the frequency or null if not valid note midi | ||
### Note.name() ⇒ <code>string</code> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| midi | <code>Number</code> | the note midi number | | ||
| tuning | <code>Number</code> | (Optional) 440 by default | | ||
<p>Get pitch class of a note. The note can be a string or a pitch array.</p> | ||
<a name="module_Note.freqToMidi"></a> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - <p>the pitch class</p> | ||
## `Note.freqToMidi` ⇒ <code>Number</code> | ||
Get the midi number from a frequency in hertz. The midi number can | ||
contain decimals (with two digits precission) | ||
| Param | Type | | ||
| ----- | ----------------------------------------- | | ||
| | <code>string</code> \| <code>Pitch</code> | | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Example** | ||
| Param | Type | | ||
| --- | --- | | ||
| frequency | <code>Number</code> | | ||
**Example** | ||
```js | ||
Note.freqToMidi(220)); //=> 57; | ||
Note.freqToMidi(261.62)); //=> 60; | ||
Note.freqToMidi(261)); //=> 59.96; | ||
Note.pc("Db3") // => "Db" | ||
[("db3", "bb6", "fx2")].map(Note.pc); // => [ "Db", "Bb", "F##"] | ||
``` | ||
<a name="module_Note.chroma"></a> | ||
## `Note.chroma` ⇒ <code>Integer</code> | ||
Return the chroma of a note. The chroma is the numeric equivalent to the | ||
pitch class, where 0 is C, 1 is C# or Db, 2 is D... 11 is B | ||
<a name="module_Note.midiToFreq"></a> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - the chroma number | ||
### Note.midiToFreq(note) ⇒ <code>Number</code> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>string</code> | the note name | | ||
<p>Get the frequency of a note</p> | ||
**Example** | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Number</code> - <p>the frequency</p> | ||
| Param | Type | Description | | ||
| ----- | ------------------------------------------ | ---------------------------------------- | | ||
| note | <code>string</code> \| <code>Number</code> | <p>the note name or midi note number</p> | | ||
**Example** | ||
```js | ||
Note.chroma("Cb") // => 11 | ||
["C", "D", "E", "F"].map(Note.chroma) // => [0, 2, 4, 5] | ||
Note.freq("A4"); // => 440 | ||
Note.freq(69); // => 440 | ||
``` | ||
<a name="module_Note.stepToLetter"></a> | ||
## `Note.stepToLetter` ⇒ <code>string</code> | ||
Given a step number return it's letter (0 = C, 1 = D, 2 = E) | ||
<a name="module_Note.chroma"></a> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - the letter | ||
### Note.chroma(note) ⇒ <code>Integer</code> | ||
| Param | Type | | ||
| --- | --- | | ||
| step | <code>number</code> | | ||
<p>Get the octave of the given pitch</p> | ||
**Example** | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - <p>the octave or null if doesn"t have an octave or not a valid note</p> | ||
| Param | Type | Description | | ||
| ----- | ------------------- | --------------- | | ||
| note | <code>string</code> | <p>the note</p> | | ||
**Example** | ||
```js | ||
Note.stepToLetter(3) // => "F" | ||
Note.oct("C#4"); // => 4 | ||
Note.oct("C"); // => null | ||
Note.oct("blah"); // => undefined | ||
``` | ||
<a name="module_Note.altToAcc"></a> | ||
## `Note.altToAcc` ⇒ <code>String</code> | ||
Given an alteration number, return the accidentals | ||
### Note.altToAcc(props, [baseNote]) ⇒ <code>String</code> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
<p>Creates a note name in scientific notation from note properties, | ||
and optionally another note name. | ||
It receives an object with:</p> | ||
<ul> | ||
<li>step: the note step (0 = C, 1 = D, ... 6 = B)</li> | ||
<li>alt: (optional) the alteration. Negative numbers are flats, positive sharps</li> | ||
<li>oct: (optional) the octave</li> | ||
</ul> | ||
<p>Optionally it receives another note as a "base", meaning that any prop not explicitly | ||
received on the first parameter will be taken from that base note. That way it can be used | ||
as an immutable "set" operator for a that base note</p> | ||
| Param | Type | | ||
| --- | --- | | ||
| alt | <code>Number</code> | | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - <p>the note name in scientific notation or null if not valid properties</p> | ||
**Example** | ||
| Param | Type | Description | | ||
| ---------- | ------------------- | --------------------------------------------------------------------------------------------------------------- | | ||
| props | <code>Object</code> | <p>the note properties</p> | | ||
| [baseNote] | <code>String</code> | <p>note to build the result from. If given, it returns the result of applying the given props to this note.</p> | | ||
**Example** | ||
```js | ||
Note.altToAcc(-3) // => "bbb" | ||
Note.from({ step: 5 }); // => "A" | ||
Note.from({ step: 1, acc: -1 }); // => "Db" | ||
Note.from({ step: 2, acc: 2, oct: 2 }); // => "E##2" | ||
Note.from({ step: 7 }); // => null | ||
Note.from({ alt: 1, oct: 3 }, "C4"); // => "C#3" | ||
``` | ||
<a name="module_Note.build"></a> | ||
## `Note.build` | ||
Deprecated. This is kept for backwards compatibility only. | ||
Use Note.from instead | ||
### Note.build(midi, useSharps) ⇒ <code>string</code> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
<a name="module_Note.simplify"></a> | ||
<p>Given a midi number, returns a note name. The altered notes will have | ||
flats unless explicitly set with the optional <code>useSharps</code> parameter.</p> | ||
## `Note.simplify` ⇒ <code>String</code> | ||
Simplify the note: find an enhramonic note with less accidentals. | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - <p>the note name</p> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - the simplfiied note or null if not valid note | ||
| Param | Type | Description | | ||
| --------- | -------------------- | ------------------------------------------------------------ | | ||
| midi | <code>number</code> | <p>the midi note number</p> | | ||
| useSharps | <code>boolean</code> | <p>(Optional) set to true to use sharps instead of flats</p> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>String</code> | the note to be simplified | | ||
| useSameAccType | <code>boolean</code> | (optional, true by default) set to true to ensure the returned note has the same accidental types that the given note | | ||
**Example** | ||
**Example** | ||
```js | ||
Note.simplify("C##") // => "D" | ||
Note.simplify("C###") // => "D#" | ||
Note.simplify("C###", false) // => "Eb" | ||
Note.simplify("B#4") // => "C5" | ||
Note.fromMidi(61); // => "Db4" | ||
Note.fromMidi(61, true); // => "C#4" | ||
// it rounds to nearest note | ||
Note.fromMidi(61.7); // => "D4" | ||
``` | ||
<a name="module_Note.enharmonic"></a> | ||
## `Note.enharmonic` ⇒ <code>String</code> | ||
Get the simplified and enhramonic note of the given one. | ||
<a name="module_Note..props"></a> | ||
**Kind**: static constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - the enhramonic note | ||
### Note~props ⇒ <code>Object</code> | ||
| Param | Type | | ||
| --- | --- | | ||
| note | <code>String</code> | | ||
<p>Get note properties. It returns an object with the following information:</p> | ||
<ul> | ||
<li>name {String}: the note name. The letter is always in uppercase</li> | ||
<li>letter {String}: the note letter, always in uppercase</li> | ||
<li>acc {String}: the note accidentals</li> | ||
<li>octave {Number}: the octave or null if not present</li> | ||
<li>pc {String}: the pitch class (letter + accidentals)</li> | ||
<li>step {Number}: number equivalent of the note letter. 0 means C ... 6 means B.</li> | ||
<li>alt {Number}: number equivalent of accidentals (negative are flats, positive sharps)</li> | ||
<li>chroma {Number}: number equivalent of the pitch class, where 0 is C, 1 is C# or Db, 2 is D...</li> | ||
<li>midi {Number}: the note midi number (IMPORTANT! it can be outside 0 to 127 range)</li> | ||
<li>freq {Number}: the frequency using an equal temperament at 440Hz</li> | ||
</ul> | ||
<p>This function <em>always</em> returns an object with all this properties, but if it"s | ||
not a valid note all properties will be null.</p> | ||
<p>The returned object can"t be mutated.</p> | ||
**Example** | ||
**Kind**: inner constant of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Object</code> - <p>an object with the properties (or an object will all properties | ||
set to null if not valid note)</p> | ||
| Param | Type | Description | | ||
| ----- | ------------------- | ------------------------------------------- | | ||
| note | <code>String</code> | <p>the note name in scientific notation</p> | | ||
**Example** | ||
```js | ||
Note.enharmonic("Db") // => "C#" | ||
Note.enhramonic("C") // => "C" | ||
Note.props("fx-3").name; // => "F##-3" | ||
Note.props("invalid").name; // => null | ||
Note.props("C#3").oct; // => 3 | ||
Note.props().oct; // => null | ||
``` | ||
<a name="module_Note.tokenize"></a> | ||
## `Note.tokenize(str)` ⇒ <code>Array</code> | ||
Split a string into tokens related to note parts. | ||
It returns an array of strings `[letter, accidental, octave, modifier]` | ||
<a name="module_Note..names"></a> | ||
It always returns an array | ||
### Note~names(accTypes) ⇒ <code>Array</code> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Array</code> - an array of note tokens | ||
<p>Get a list of note names (pitch classes) within a octave</p> | ||
| Param | Type | | ||
| --- | --- | | ||
| str | <code>String</code> | | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Example** | ||
| Param | Type | Description | | ||
| -------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| accTypes | <code>string</code> | <p>(Optional, by default " b#"). A string with the accidentals types: " " means no accidental, "#" means sharps, "b" mean flats, can be combined (see examples)</p> | | ||
**Example** | ||
```js | ||
Note.tokenize("C#2") // => ["C", "#", "2", ""] | ||
Note.tokenize("Db3 major") // => ["D", "b", "3", "major"] | ||
Note.tokenize("major") // => ["", "", "", "major"] | ||
Note.tokenize("##") // => ["", "##", "", ""] | ||
Note.tokenize() // => ["", "", "", ""] | ||
Note.names(" b"); // => [ "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" ] | ||
Note.names(" #"); // => [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ] | ||
``` | ||
<a name="module_Note.name"></a> | ||
## `Note.name()` ⇒ <code>string</code> | ||
Given a note name, return the note name or null if not valid note. | ||
The note name will ALWAYS have the letter in upercase and accidentals | ||
using # or b | ||
<a name="module_Note..tokenize"></a> | ||
Can be used to test if a string is a valid note name. | ||
### Note~tokenize(str) ⇒ <code>Array</code> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
<p>Split a string into tokens related to note parts. | ||
It returns an array of strings <code>[letter, accidental, octave, modifier]</code></p> | ||
<p>It always returns an array</p> | ||
| Type | | ||
| --- | | ||
| <code>Pitch</code> \| <code>string</code> | | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Array</code> - <p>an array of note tokens</p> | ||
**Example** | ||
| Param | Type | | ||
| ----- | ------------------- | | ||
| str | <code>String</code> | | ||
**Example** | ||
```js | ||
Note.name("cb2") // => "Cb2" | ||
["c", "db3", "2", "g+", "gx4"].map(Note.name) // => ["C", "Db3", null, null, "G##4"] | ||
Note.tokenize("C#2"); // => ["C", "#", "2", ""] | ||
Note.tokenize("Db3 major"); // => ["D", "b", "3", "major"] | ||
Note.tokenize("major"); // => ["", "", "", "major"] | ||
Note.tokenize("##"); // => ["", "##", "", ""] | ||
Note.tokenize(); // => ["", "", "", ""] | ||
``` | ||
<a name="module_Note.pc"></a> | ||
## `Note.pc()` ⇒ <code>string</code> | ||
Get pitch class of a note. The note can be a string or a pitch array. | ||
<a name="module_Note..midi"></a> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - the pitch class | ||
### Note~midi(note) ⇒ <code>Integer</code> | ||
| Type | | ||
| --- | | ||
| <code>string</code> \| <code>Pitch</code> | | ||
<p>Get the note midi number. It always return a number between 0 and 127</p> | ||
**Example** | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - <p>the midi number or null if not valid pitch</p> | ||
**See**: midi.toMidi | ||
| Param | Type | Description | | ||
| ----- | ------------------------------------------ | ------------------------------------------- | | ||
| note | <code>string</code> \| <code>Number</code> | <p>the note to get the midi number from</p> | | ||
**Example** | ||
```js | ||
Note.pc("Db3") // => "Db" | ||
["db3", "bb6", "fx2"].map(Note.pc) // => [ "Db", "Bb", "F##"] | ||
Note.midi("C4"); // => 60 | ||
Note.midi(60); // => 60 | ||
``` | ||
<a name="module_Note.midi"></a> | ||
## `Note.midi(note)` ⇒ <code>Integer</code> | ||
Get the note midi number. It always return a number between 0 and 127 | ||
<a name="module_Note..freqToMidi"></a> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - the midi number or null if not valid pitch | ||
**See**: midi.toMidi | ||
### Note~freqToMidi(frequency) ⇒ <code>Number</code> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>string</code> \| <code>Number</code> | the note to get the midi number from | | ||
<p>Get the midi number from a frequency in hertz. The midi number can | ||
contain decimals (with two digits precission)</p> | ||
**Example** | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
| Param | Type | | ||
| --------- | ------------------- | | ||
| frequency | <code>Number</code> | | ||
**Example** | ||
```js | ||
Note.midi("C4") // => 60 | ||
Note.midi(60) // => 60 | ||
Note.freqToMidi(220)); //=> 57; | ||
Note.freqToMidi(261.62)); //=> 60; | ||
Note.freqToMidi(261)); //=> 59.96; | ||
``` | ||
<a name="module_Note.freq"></a> | ||
## `Note.freq(note)` ⇒ <code>Number</code> | ||
Get the frequency of a note | ||
<a name="module_Note..stepToLetter"></a> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Number</code> - the frequency | ||
### Note~stepToLetter(step) ⇒ <code>string</code> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>string</code> \| <code>Number</code> | the note name or midi note number | | ||
<p>Given a step number return it's letter (0 = C, 1 = D, 2 = E)</p> | ||
**Example** | ||
```js | ||
Note.freq("A4") // => 440 | ||
Note.freq(69) // => 440 | ||
``` | ||
<a name="module_Note.oct"></a> | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - <p>the letter</p> | ||
## `Note.oct(note)` ⇒ <code>Integer</code> | ||
Get the octave of the given pitch | ||
| Param | Type | | ||
| ----- | ------------------- | | ||
| step | <code>number</code> | | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>Integer</code> - the octave or null if doesn"t have an octave or not a valid note | ||
**Example** | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| note | <code>string</code> | the note | | ||
**Example** | ||
```js | ||
Note.oct("C#4") // => 4 | ||
Note.oct("C") // => null | ||
Note.oct("blah") // => undefined | ||
Note.stepToLetter(3); // => "F" | ||
``` | ||
<a name="module_Note.from"></a> | ||
## `Note.from(props, [baseNote])` ⇒ <code>String</code> | ||
Creates a note name in scientific notation from note properties, | ||
and optionally another note name. | ||
It receives an object with: | ||
- step: the note step (0 = C, 1 = D, ... 6 = B) | ||
- alt: (optional) the alteration. Negative numbers are flats, positive sharps | ||
- oct: (optional) the octave | ||
<a name="module_Note..altToAcc"></a> | ||
Optionally it receives another note as a "base", meaning that any prop not explicitly | ||
received on the first parameter will be taken from that base note. That way it can be used | ||
as an immutable "set" operator for a that base note | ||
### Note~altToAcc(alt) ⇒ <code>String</code> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - the note name in scientific notation or null if not valid properties | ||
<p>Given an alteration number, return the accidentals</p> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| props | <code>Object</code> | the note properties | | ||
| [baseNote] | <code>String</code> | note to build the result from. If given, it returns the result of applying the given props to this note. | | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Example** | ||
| Param | Type | | ||
| ----- | ------------------- | | ||
| alt | <code>Number</code> | | ||
**Example** | ||
```js | ||
Note.from({ step: 5 }) // => "A" | ||
Note.from({ step: 1, acc: -1 }) // => "Db" | ||
Note.from({ step: 2, acc: 2, oct: 2 }) // => "E##2" | ||
Note.from({ step: 7 }) // => null | ||
Note.from({alt: 1, oct: 3}, "C4") // => "C#3" | ||
Note.altToAcc(-3); // => "bbb" | ||
``` | ||
<a name="module_Note.fromMidi"></a> | ||
## `Note.fromMidi(midi, useSharps)` ⇒ <code>string</code> | ||
Given a midi number, returns a note name. The altered notes will have | ||
flats unless explicitly set with the optional `useSharps` parameter. | ||
<a name="module_Note..simplify"></a> | ||
**Kind**: static method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>string</code> - the note name | ||
### Note~simplify(note, useSameAccType) ⇒ <code>String</code> | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| midi | <code>number</code> | the midi note number | | ||
| useSharps | <code>boolean</code> | (Optional) set to true to use sharps instead of flats | | ||
<p>Simplify the note: find an enhramonic note with less accidentals.</p> | ||
**Example** | ||
**Kind**: inner method of [<code>Note</code>](#module_Note) | ||
**Returns**: <code>String</code> - <p>the simplfiied note or null if not valid note</p> | ||
| Param | Type | Description | | ||
| -------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | ||
| note | <code>String</code> | <p>the note to be simplified</p> | | ||
| useSameAccType | <code>boolean</code> | <p>(optional, true by default) set to true to ensure the returned note has the same accidental types that the given note</p> | | ||
**Example** | ||
```js | ||
Note.fromMidi(61) // => "Db4" | ||
Note.fromMidi(61, true) // => "C#4" | ||
// it rounds to nearest note | ||
Note.fromMidi(61.7) // => "D4" | ||
Note.simplify("C##"); // => "D" | ||
Note.simplify("C###"); // => "D#" | ||
Note.simplify("C###", false); // => "Eb" | ||
Note.simplify("B#4"); // => "C5" | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
189608
39
433
1
1426
1