tonal-interval
Advanced tools
Comparing version 0.66.0 to 0.68.1
@@ -9,2 +9,30 @@ 'use strict'; | ||
/** | ||
* A collection of functions to obtain music interval properties. | ||
* | ||
* The intervals are strings in shorthand notation. Two variations are supported: | ||
* | ||
* - standard shorthand notation: type and number, for example: 'M3', 'd-4' | ||
* - inverse shorthand notation: number and then type, for example: '3M', '-4d' | ||
* | ||
* The problem with the standard shorthand notation is that some strings can be | ||
* parsed as notes or intervals, for example: 'A4' can be note A in 4th octave | ||
* or an augmented four. To remove ambiguity, the prefered notation in tonal is the | ||
* inverse shortand notation. | ||
* | ||
* NOTE: this module is exported in tonal as ivl | ||
* | ||
* @example | ||
* var interval = require('tonal-interval') | ||
* interval.semitones('4P') // => 5 | ||
* interval.invert('3m') // => '6M' | ||
* interval.simplify('9m') // => '2m' | ||
* | ||
* @example | ||
* // from tonal | ||
* var tonal = require('tonal') | ||
* tonal.ivl.invert('4P') // => '5P' | ||
* | ||
* @module interval | ||
*/ | ||
/** | ||
* Get interval name. Can be used to test if it's an interval. It accepts intervals | ||
@@ -21,3 +49,3 @@ * as pitch or string in shorthand notation or tonal notation. It returns always | ||
function toInterval (ivl) { | ||
var i = tonalPitch.asIvlPitch(ivl) | ||
var i = tonalPitch.asIvlPitch(ivl); | ||
return i ? tonalPitch.strIvl(i) : null | ||
@@ -37,3 +65,3 @@ } | ||
function num (ivl) { | ||
var p = props(ivl) | ||
var p = props(ivl); | ||
return p ? p.num : null | ||
@@ -55,3 +83,3 @@ } | ||
function value (ivl) { | ||
var p = props(ivl) | ||
var p = props(ivl); | ||
return p ? p.num * p.dir : null | ||
@@ -76,5 +104,5 @@ } | ||
function props (ivl) { | ||
var i = tonalPitch.asIvlPitch(ivl) | ||
var i = tonalPitch.asIvlPitch(ivl); | ||
if (!i) return null | ||
var d = tonalPitch.decode(i) | ||
var d = tonalPitch.decode(i); | ||
return { num: d[0] + 1 + d[2] * 7, alt: d[1], dir: i[2] } | ||
@@ -95,5 +123,5 @@ } | ||
if (!props || props.num < 1) return null | ||
var octs = Math.floor((props.num) / 7) | ||
var simple = props.num - 7 * octs | ||
return intervalNotation.build(simple, props.alt, octs, props.dir) | ||
var octs = Math.floor((props.num) / 8); | ||
var simple = props.num - 7 * octs; | ||
return intervalNotation.build(simple, props.alt || 0, octs, props.dir) | ||
} | ||
@@ -112,3 +140,3 @@ | ||
function semitones (ivl) { | ||
var i = tonalPitch.asIvlPitch(ivl) | ||
var i = tonalPitch.asIvlPitch(ivl); | ||
return i ? tonalPitch.height(i) : null | ||
@@ -118,5 +146,5 @@ } | ||
// interval numbers | ||
var IN = [1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7] | ||
var IN = [1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7]; | ||
// interval qualities | ||
var IQ = 'P m M m M P d P m M m M'.split(' ') | ||
var IQ = 'P m M m M P d P m M m M'.split(' '); | ||
@@ -135,10 +163,10 @@ /** | ||
function fromSemitones (num) { | ||
var d = num < 0 ? -1 : 1 | ||
var n = Math.abs(num) | ||
var c = n % 12 | ||
var o = Math.floor(n / 12) | ||
var d = num < 0 ? -1 : 1; | ||
var n = Math.abs(num); | ||
var c = n % 12; | ||
var o = Math.floor(n / 12); | ||
return d * (IN[c] + 7 * o) + IQ[c] | ||
} | ||
var CLASSES = [0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1] | ||
var CLASSES = [0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]; | ||
/** | ||
@@ -163,8 +191,8 @@ * Get the [interval class](https://en.wikipedia.org/wiki/Interval_class) | ||
function ic (ivl) { | ||
var i = tonalPitch.asIvlPitch(ivl) | ||
var s = i ? tonalPitch.chr(i) : Math.round(ivl) | ||
var i = tonalPitch.asIvlPitch(ivl); | ||
var s = i ? tonalPitch.chr(i) : Math.round(ivl); | ||
return isNaN(s) ? null : CLASSES[Math.abs(s) % 12] | ||
} | ||
var TYPES = 'PMMPPMM' | ||
var TYPES = 'PMMPPMM'; | ||
/** | ||
@@ -181,3 +209,3 @@ * Get interval type. Can be perfectable (1, 4, 5) or majorable (2, 3, 6, 7) | ||
function type (ivl) { | ||
var i = tonalPitch.asIvlPitch(ivl) | ||
var i = tonalPitch.asIvlPitch(ivl); | ||
return i ? TYPES[tonalPitch.decode(i)[0]] : null | ||
@@ -200,8 +228,8 @@ } | ||
var invert = tonalPitch.ivlFn(function (i) { | ||
var d = tonalPitch.decode(i) | ||
var d = tonalPitch.decode(i); | ||
// d = [step, alt, oct] | ||
var step = (7 - d[0]) % 7 | ||
var alt = TYPES[d[0]] === 'P' ? -d[1] : -(d[1] + 1) | ||
var step = (7 - d[0]) % 7; | ||
var alt = TYPES[d[0]] === 'P' ? -d[1] : -(d[1] + 1); | ||
return tonalPitch.encode(step, alt, d[2], tonalPitch.dir(i)) | ||
}) | ||
}); | ||
@@ -224,8 +252,8 @@ /** | ||
// decode to [step, alt, octave] | ||
var dec = tonalPitch.decode(i) | ||
var dec = tonalPitch.decode(i); | ||
// if it's not 8 reduce the octaves to 0 | ||
if (dec[0] !== 0 || dec[2] !== 1) dec[2] = 0 | ||
if (dec[0] !== 0 || dec[2] !== 1) dec[2] = 0; | ||
// encode back | ||
return tonalPitch.encode(dec[0], dec[1], dec[2], tonalPitch.dir(i)) | ||
}) | ||
}); | ||
@@ -242,2 +270,2 @@ exports.toInterval = toInterval; | ||
exports.invert = invert; | ||
exports.simplify = simplify; | ||
exports.simplify = simplify; |
@@ -115,5 +115,5 @@ /** | ||
if (!props || props.num < 1) return null | ||
var octs = Math.floor((props.num) / 7) | ||
var octs = Math.floor((props.num) / 8) | ||
var simple = props.num - 7 * octs | ||
return build(simple, props.alt, octs, props.dir) | ||
return build(simple, props.alt || 0, octs, props.dir) | ||
} | ||
@@ -120,0 +120,0 @@ |
{ | ||
"name": "tonal-interval", | ||
"version": "0.66.0", | ||
"version": "0.68.1", | ||
"description": "Music interval creation and manipulation", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/danigb/tonal/packages/interval", |
@@ -36,2 +36,3 @@ var test = require('tape') | ||
t.equal(ivl.fromProps({ num: -1 }), null) | ||
t.equal(ivl.fromProps({ num: 7 }), '7M') | ||
t.equal(ivl.fromProps(), null) | ||
@@ -38,0 +39,0 @@ t.end() |
27321
588