saebekassebil / teoria

Javascript taught Music Theory
http://saebekassebil.github.io/teoria
MIT License
1.31k stars 114 forks source link

Teoria.js

Teoria.js is a lightweight and fast JavaScript library for music theory, both Jazz and Classical. It aims at providing an intuitive programming interface for music software (such as Sheet Readers, Sheet Writers, MIDI Players etc.).

Features

Usage

$ npm install teoria

Can be used with both Node and Browserify/webpack/etc.

... or less preferable

Include the bundled build file, teoria.js from this repository, directly:

<script src="https://github.com/saebekassebil/teoria/raw/master/path/to/teoria.js"></script>

Syntax

This is just a short introduction to what teoria-code looks like, for a technical library reference, look further down this document.


// Create notes:
var a4 = teoria.note('a4');       // Scientific notation
var g5 = teoria.note("g''");      // Helmholtz notation
var c3 = teoria.note.fromKey(28); // From a piano key number

// Find and create notes based on intervals
teoria.interval(a4, g5);    // Returns a Interval object representing a minor seventh
teoria.interval(a4, 'M6');  // Returns a Note representing F#5
a4.interval('m3');          // Returns a Note representing C#4
a4.interval(g5);            // Returns a Interval object representing a minor seventh
a4.interval(teoria.note('bb5')).invert(); // Returns a Interval representing a major seventh

// Create scales, based on notes.
a4.scale('mixolydian').simple();  // Returns: ["a", "b", "c#", "d", "e", "f#", "g"]
a4.scale('aeolian').simple();     // Returns: ["a", "b", "c", "d", "e", "f", "g"]
g5.scale('ionian').simple();      // Returns: ["g", "a", "b", "c", "d", "e", "f#"]
g5.scale('dorian');               // Returns a Scale object

// Create chords with the powerful chord parser
a4.chord('sus2').name;    // Returns the name of the chord: 'Asus2'
c3.chord('m').name;       // Returns 'Cm'
teoria.chord('Ab#5b9');   // Returns a Chord object, representing a Ab#5b9 chord
g5.chord('dim');          // Returns a Chord object, representing a Gdim chord

// Calculate note frequencies or find the note corresponding to a frequency
teoria.note.fromFrequency(467); // Returns: {'note':{...},'cents':3.102831} -> A4# a little out of tune.
a4.fq(); // Outputs 440
g5.fq(); // Outputs 783.9908719634985

// teoria allows for crazy chaining:
teoria.note('a')    // Create a note, A3
  .scale('lydian')  // Create a lydian scale with that note as root (A lydian)
  .interval('M2')   // Transpose the whole scale a major second up (B lydian)
  .get('third')     // Get the third note of the scale (D#4)
  .chord('maj9')    // Create a maj9 chord with that note as root (D#maj9)
  .toString();      // Make a string representation: 'D#maj9'

Documentation

teoria.note (name | coord[, duration])

name - The name argument is the note name as a string. The note can both be expressed in scientific and Helmholtz notation. Some examples of valid note names: Eb4, C#,,, C4, d#'', Ab2

coord - If the first argument isn't a string, but a coord array, it will instantiate a Note instance.

duration - The duration argument is an optional object argument. The object has two also optional parameters:

teoria.note.fromKey(key)

A static method that returns an instance of Note set to the note at the given piano key, where A0 is key number 1. See Wikipedia's piano key article for more information.

teoria.note.fromFrequency(fq)

A static method returns an object containing two elements:

note - A Note which corresponds to the closest note with the given frequency

cents - A number value of how many cents the note is out of tune

teoria.note.fromMIDI(note)

note - A number ranging from 0-127 representing a MIDI note value

teoria.note.fromString(note)

note - The name argument is the note name as a string. The note can both be expressed in scientific and Helmholtz notation. Some examples of valid note names: Eb4, C#,,, C4, d#'', Ab2

Note.name()

Note.octave()

Note.duration

Note.accidental()

Note.accidentalValue()

Note#key([whitenotes])

whitenotes - If this parameter is set to true only the white keys will be counted when finding the key number. This is mostly for internal use.

Note#midi()

Note#fq([concertPitch])

concertPitch - If supplied this number will be used instead of the normal concert pitch which is 440hz. This is useful for some classical music.

Note#chroma()

This allows for easy enharmonic checking:

teoria.note('e').chroma() === teoria.note('fb').chroma();

The chroma number is ranging from pitch class C which is 0 to 11 which is B

Note#scale(scaleName)

scaleName - The name of the scale to be returned. 'minor', 'chromatic', 'ionian' and others are valid scale names.

Note#interval(interval)

Look at the documentation for teoria.interval

Note#transpose(interval)

Note#chord([name])

name - The name attribute is the last part of the chord symbol. Examples: 'm7', '#5b9', 'major'. If the name parameter isn't set, a standard major chord will be returned.

Note#helmholtz()

Example: teoria.note('A5').helmholtz() -> "a''"

Note#scientific()

Example: teoria.note("ab'").scientific() -> "Ab4"

Note#enharmonics(oneAccidental)

oneAccidental - Boolean, if set to true, only enharmonic notes with one accidental is returned. E.g. results such as 'eb' and 'c#' but not 'ebb' and 'cx'

teoria.note('c').enharmonics().toString();
// -> 'dbb, b#'

teoria.note('c').enharmonics(true).toString();
// -> 'b#'

Note#durationInSeconds(bpm, beatUnit)

Note#solfege(scale, showOctaves)

scale - An instance of Scale, which is the context of the solfege step measuring

showOctaves - A boolean. If set to true, a "Helmholtz-like" notation will be used if there's bigger intervals than an octave

Note#durationName()

Examples: teoria.note('A', 8).durationName() -> 'eighth', teoria.note('C', 16).durationName() -> 'sixteenth'

Note#scaleDegree(scale)

scale - An instance of Scale which is the context of the degree measuring

Note#toString([dontShow])

dontShow - If set to true the octave will not be included in the returned string.

Chord(root, chord)

root - A Note instance which is to be the root of the chord

chord - A string containing the chord symbol. This can be anything from simple chords, to super-advanced jazz chords thanks to the detailed and robust chord parser engine. Example values: 'm', 'm7', '#5b9', '9sus4 and '#11b5#9'

teoria.chord(name || note[, octave || symbol])

name - A string containing the full chord symbol, with note name. Examples: 'Ab7', 'F#(#11b5)'

note - Instead of supplying a string containing the full chord symbol, one can pass a Note object instead. The note will be considered root in the new chord object

octave - If the first argument of the function is a chord name (typeof "string"), then the second argument is an optional octave number (typeof "number") of the root.

symbol - A string containing the chord symbol (excluding the note name)

Chord.name

Chord.root

Chord#notes()

Chord#simple()

Chord#bass()

Chord#voicing([voicing])

voicing - An optional array of intervals in simple-format that represents the current voicing of the chord.

Here's an example:

var bbmaj = teoria.chord('Bbmaj7');
// Default voicing:
bbmaj.voicing();  // #-> ['P1', 'M3', 'P5', 'M7'];
bbmaj.notes();    // #-> ['bb', 'd', 'f', 'a'];

// New voicing
bbmaj.voicing(['P1', 'P5', 'M7', 'M10']);
bbmaj.notes();    // #-> ['bb', 'f', 'a', 'd'];

NB: Note that above returned results are pseudo-results, as they will be returned wrapped in Interval and Note objects.

Chord#quality()

Chord#get(interval)

interval - A string name of an interval, for example 'third', 'fifth', 'ninth'.

Chord#dominant([additional])

additional - Additional chord extension, for example: 'b9' or '#5'

Chord#subdominant([additional])

additional - Like the dominant's.

Chord#parallel([additional])

additional - Like the dominant's

Chord#chordType()

Chord#interval(interval)

Chord#transpose(interval)

Chord#toString()

Scale(tonic, scale)

tonic - A Note which is to be the tonic of the scale

scale - Can either be a name of a scale (string), or an array of absolute intervals that defines the scale. The scales supported by default are:

teoria.scale(tonic, scale)

teoria.Scale.KNOWN_SCALES

Scale.name

Scale.tonic

Scale#notes()

Scale#simple()

Scale#type()

Scale#get(index)

index - Can be a number referring to the scale step, or the name (string) of the scale step. E.g. 'first', 'second', 'fourth', 'seventh'.

Scale#solfege(index, showOctaves)

index Same as Scale#get

showOctaves - A boolean meaning the same as showOctaves in Note#solfege

teoria.interval(from, to)

teoria.interval(string: from)

teoria.interval(Note: from, string: to)

teoria.interval(Note: from, Interval: to)

teoria.interval(Note: from, Note: to)

teoria.interval.from -> Interval.from
teoria.interval.between -> Interval.between
teoria.interval.invert -> Interval.invert
teoria.interval.toCoord -> Interval.toCoord

Interval(coord)

Interval.toCoord(simpleInterval)

Interval.from(from, to)

from - The Note which is the root of the measuring

to - A Interval

Interval.between(from, to)

from and to are two Notes which are the notes that the interval is measured from. For example if 'a' and 'c' are given, the resulting interval object would represent a minor third.

Interval.between(teoria.note("a"), teoria.note("c'")) -> teoria.interval('m3')

Interval.invert(simpleInterval)

simpleInterval - An interval represented in simple string form. Examples:

'm' = minor, 'M' = major, 'A' = augmented and 'd' = diminished

The number may be prefixed with a - to signify that its direction is down. E.g.:

m-3 means a descending minor third, and P-5 means a descending perfect fifth.

Interval.coord

Interval.number()

Interval.value()

Interval.toString()

Interval.base()

Interval.type()

Interval.quality([verbose])

verbose is set to a truish value, then long quality names are returned: 'doubly diminished', 'diminished', 'minor', etc.

Interval.direction([dir])

dir - If supplied, then the interval's direction is to the newDirection which is either 'up' or 'down'

Interval#semitones()

Interval#simple([ignoreDirection])

ignoreDirection - An optional boolean that, if set to true, returns the "direction-agnostic" interval. That is the interval with a positive number.

teoria.interval('M17').simple();    // #-> 'M3'
teoria.interval('m23').simple();    // #-> 'm2'
teoria.interval('P5').simple();     // #-> 'P5'
teoria.interval('P-4').simple();    // #-> 'P-4'

// With ignoreDirection = true
teoria.interval('M3').simple(true);     // #->'M3'
teoria.interval('m-10').simple(true);   // #-> 'm3'

NB: Note that above returned results are pseudo-results, as they will be returned wrapped in Interval objects.

Interval#octaves()

Interval#isCompound()

Interval#add(interval)

Interval#equal(interval)

Interval#greater(interval)

Interval#smaller(interval)

Interval#invert()

Interval#qualityValue() - internal