tonal
is a functional music theory library. It provides functions to manipulate tonal elements of music (pitches, chords, scales, keys). It deals with abstractions (not actual music).
Think like an underscorejs (or better: ramdajs) library for music theory.
This library is under active development.
## Example
var tonal = require('tonal')
// midi and frequency
tonal.toMidi('A4') // => 64
tonal.fromMidi(60) // => 'C4'
tonal.toFreq('A4') // => 440
tonal.fromFreq(220) // => 'A3'
// note transposition
tonal.transpose('D4', '2M') // => 'E#4'
// interval distance between notes
tonal.distance('C', 'G') // => '5P'
// distance in semitones
tonal.semitones(tonal.dist('C', 'G')) // => 7
// partial function application
var upFifth = tonal.tr('P5')
upFifth('c3') // => 'G3'
upFifth('g3') // => 'D4'
// work with arrays
tonal.asArr('c db eb f gb') // => ['C', 'Db', 'Eb', 'F', 'Gb']
// map list of notes using functions
tonal.map(tonal.tr('3M'), 'c d e') // => ['E4', 'F#4', 'G#4']
// get pitch classes using pc function
tonal.map(tonal.pc, 'C2 Eb5 gx4') // => ['C', 'Eb', 'G##']
// map functions (partial map application)
var pcs = tonal.map(tonal.pc)
pcs('C2 db3 e5') // => ['C', 'Db', 'E']
var up5 = tonal.map(tonal.tr('5P'))
up5('c d e') // => ['G', 'A', 'B']
// Create note ranges
tonal.chromatic('C4, F4, D4') // => [ 'C4', 'Db4', 'D4', 'Eb4', 'E4', 'F4', 'E4', 'Eb4', 'D4' ]
// Filter ranges to certain notes
tonal.scaleRange('C Eb G Bb', 'C3, C4, C3') // => ['C3', 'Eb3', 'G3', 'Bb3', 'C4', 'Bb3', 'G3', 'Eb3', 'C3']
// create harmonizers
var maj7 = tonal.harmonizer('P1 M3 P5 M7')
maj7('C2') // => ['C2', 'E2', 'G2', 'B2']
// extract intervals
tonal.harmonics('C Eb G Bb') // => ['1P', '3m', '5P', '7m']
Although tonal
is a work in progress, currently is implemented (but not all released):
- Note, intervals, transposition, distances, enharmonics
- Midi and frequency conversion
- Scales, chords, dictionaries
- Work with collection of notes: gamut, harmonizer
- Pitch sets and binary representations
- Keys, keys signatures, key scales and chords, key detection
This library is evolving with this ideas in mind:
- Functional: no classes, no side effects, no mutations. Just functions, data-in data-out. Most of the functions has the data to operate on as last argument and lot of functions are currified.
- Notes and intervals are represented with strings, instead of objects. Easy and concise code.
- Small and fast
- Modular
- Different notations: scientific notation by default. Helmholtz coming. Change it easily.
- Documented: all public functions are documented inside the code. Aside the generated documentation (in API.md file) a 'usage' guides are provided for each module.
- Learneable: since all the modules share the same philosophy is easy to work with them.
- Tested: carefully tested with coverage support.
- Advanced features: chord and scale detection, binary sets, chord progressions, key signatures...
First of all, because I want to learn:
Reinventing the wheel is bad for business, but it’s great for learning *
Also, I want a complete library, where I can model all what I learn, with some (for me) esoteric features like interval classes, binary scales and other weird stuff.
## What
Tonal itself is built from a collection of modules. Some of they are exposed in the tonal
package that can be installed via npm: npm i tonal
. Some others must be required explicitly, like scales: npm i tonal-scales
Although you can install any of this modules individually, they are all included in the tonal
package by default:
- noteName: get the note name
- chroma: get chroma of a note
- pc: get pitch class of a note
- enharmonics: get a list of note enharmonics
- simpleEnh: get the simplest enharmonic of a note
- ivlName: get the interval name
- semitones: get the size of an interval in semitones
- fromSemitones: create an interval from a semitones number
- ic: get interval class
- itype: get interval type
- invert: invert interval
- simplify: simplify interval
- isMidiNum: test if the given number is a valid midi note number
- toMidi: get midi note number from a note
- fromMidi: get note name from midi number
- fromMidiS: get note name from midi number using sharps when altered
- toFreq: get frequency of a note name
- fromFreq: get note name from frequency
- cents: get distance in cents between two notes or frequencies
- toEqualTemp: create a function to convert notes to frequencies using equal temperament
- fromEqualTemp: create a function to convert frequencies to notes using equal temperament
- transpose: transpose notes by intervals. Can be used to add intervals.
- trFifths: transpose a note by a number of perfect fifths
- distance: find the interval distance between two notes
- distInSemitones: get the distance between notes measured in semitones
- asArr: split a strings into arrays
- map: map a function to a list
- filter: filter a list using a function
- harmonizer: return a function that harmonizes notes using a list of intervals
- harmonize: given a note and a list of intervals, harmonize the note with the intervals
- harmonics: Given a list of notes, return the intervals from the first note to the rest.
- rotate: rotate a list
- rotateAsc: rotate an list of ascending pitches keeping the asceding property after rotation
- select: select some elements from a list
- sort: sort a list of notes or intervals
- shuffle: shuffle an array
- scaleFilter: filter notes by a scale
- range: create a range of notes
- scaleRange: create a range using a scale
- chromatic: create a chromatic range
- cycleOfFifths: create a cycle of fifths range
To use them, this modules need to be installed and required explicitly. For example: npm i --save tonal-scale
and var scale = require('tonal-scale')
- get: get a scale from name
- build: build a scale from type or intervals and tonic
- names: get a list of all scale names
- get: get a chord from name
- build: build a chord from type or intervals and tonic
- names: get a list of all chord names
- scale: Get the scale of a given key
- relative: Given a key in one mode, find it's relative in other.
- names: Get a list of mode names.
- isKeyMode: test if a string is a valid key mode
- build: build a key from mode and tonic
- fromAlter: create a key from alteration
- fromAcc: create a key from accidentals
- fromName: create a key from name
- asKey: try to interpret the object as a key
- alteration: get key alteration
- accidentals: get key accidentals
- alteredNotes: get the altered notes of a key
- build: build a progression from a list of chords (in roman numerals) and a tonic
- romanRegex: get a regex to match roman numerals.
- parseRomanChord: parse chord expressed with roman numerals.
To build or test this library you first you need is to clone this repository. Then, since it's a multimodule package if you run npm test
you only run test for the tonal
package (the facade). To run the test of all the modules you can run: npm run modules-install && npm run modules-test
.
Or if you prefer npm run test-ci
to run all in one command.
The API Reference documentation is generated with jsdoc2md
package (not included in dependencies) and then the output copied to the README of each package.
The distributable tonal-min.js
file is generated with npm run dist
This library takes inspiration from other music theory libraries:
- Teoria: https://github.com/saebekassebil/teoria
- Impro-Visor: https://www.cs.hmc.edu/~keller/jazz/improvisor/
- MusicKit: https://github.com/benzguo/MusicKit
- Music21: http://web.mit.edu/music21/doc/index.html
- Sharp11: https://github.com/jsrmath/sharp11
MIT License