Skip to content

Commit

Permalink
Merge pull request #37 from saebekassebil/coords
Browse files Browse the repository at this point in the history
Use coords internally to represent notes and intervals
  • Loading branch information
saebekassebil committed Jul 8, 2013
2 parents b83d9ea + e45f725 commit 8c029dc
Show file tree
Hide file tree
Showing 12 changed files with 487 additions and 551 deletions.
30 changes: 16 additions & 14 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@
"TeoriaScale",
"teoria",

"kNotes",
"kNoteIndex",
"kDurations",
"kIntervals",
"kIntervalIndex",
"kQualityLong",
"kQualityTemp",
"kValidQualities",
"kQualityInversion",
"kAlterations",
"kSymbols",
"kChordShort",
"kAccidentalSign",
"kAccidentalValue",
"kStepNumber",
"kIntervalSolfege",
"kQualityLong",

"getDistance",
"pad"
"pad",
"sum",
"mul",
"add",
"sub",
"A4",
"accidentals",
"sharp",
"fifths",
"notes",
"intervals",
"intervalFromFifth",
"intervalsIndex"
],

"node": true,
Expand All @@ -34,7 +36,6 @@
"maxlen": 80,
"strict": false,
"devel": true,
"curly": true,
"newcap": true,
"noempty": true,
"nonew": true,
Expand All @@ -46,5 +47,6 @@
"latedef": true,
"undef": true,
"evil": false,
"unused": true
"unused": true,
"laxcomma": true
}
93 changes: 53 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,15 @@ teoria.note('a') // Create a note, A3
Documentation
------------------------


## TeoriaNote(name[, duration])
- This function construct a teoria.note object.
## 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 `TeoriaNote` instance.

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

Expand All @@ -132,12 +133,6 @@ The object has two also optional parameters:

- `dots` - The number of dots attached to the note. Defaults to `0`.

### teoria.note (TeoriaNote)

The teoria.note object is teoria's interpretation and representation of a
musical note. When calling teoria.note you're actually instantiating a
`TeoriaNote` object.

### teoria.note.fromKey(key)
A static method that returns an instance of TeoriaNote set to the note
at the given 88 key piano position, where A0 is key number 1.
Expand All @@ -156,23 +151,29 @@ A static method returns an object containing two elements:

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

#### TeoriaNote.name
### teoria.note.fromString(note)
- Returns an instance of TeoriaNote representing the note name

*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`

#### TeoriaNote.name()
- The name of the note, in lowercase letter (*only* the name, not the
accidental signs)

#### TeoriaNote.octave
#### TeoriaNote.octave()
- The numeric value of the octave of the note

#### TeoriaNote.duration
- The duration object as described in the constructor for TeoriaNote

#### TeoriaNote.accidental
- An object containing two elements:
#### TeoriaNote.accidental()
- Returns the string symbolic of the accidental sign (`x`, `#`, `b` or `bb`)

*sign* - The string symbolic of the accidental sign `#`, `x`, `b` or `bb`

*value* - The numeric value (mostly used internally) of the sign:
`# = 1, x = 2, b = -1, bb = -2`
#### TeoriaNote.accidentalValue()
- Returns the numeric value (mostly used internally) of the sign:
`x = 2, # = 1, b = -1, bb = -2`

#### TeoriaNote#key([whitenotes])
- Returns the piano key number. Fx A4 would return 49
Expand Down Expand Up @@ -383,8 +384,8 @@ absolute intervals that defines the scale. The default supported scales are:
### teoria.scale(tonic, scale)
- Sugar function for constructing a new `TeoriaScale` object

### TeoriaScale.notes
- An array of `TeoriaNote`s which is the scale's notes
### TeoriaScale.notes()
- Returns an array of `TeoriaNote`s which is the scale's notes

### TeoriaScale.name
- The name of the scale (if available). Type `string` or `undefined`
Expand Down Expand Up @@ -424,28 +425,21 @@ scale step. Example 'first', 'second', 'fourth', 'seventh'.
- A sugar function for the `#from` and `#between` methods of the same namespace and
for creating `TeoriaInterval` objects.

#### teoria.interval(`string`: from[, `string`: direction])
- Returns a `TeoriaInterval` object, with the given interval

*from* - An interval in "simple-format" such as 'M2' for major second, and 'P5' for perfect fifth. Look further down for more details on this format.
#### teoria.interval(`string`: from)
- A sugar method for the `teoria.interval.toCoord` function

*direction* - An optional direction string, either `'up'` or `'down'`. Defaults to `'up'`

#### teoria.interval(`TeoriaNote`: from, `string`: to[, `string`: direction)
#### teoria.interval(`TeoriaNote`: from, `string`: to)
- A sugar method for the `teoria.interval.from` function

#### teoria.interval(`TeoriaNote`: from, `TeoriaNote`: to)
- A sugar method for the `teoria.interval.between` function

#### teoria.interval.from(from, to[, direction])
#### teoria.interval.from(from, to)
- Returns a note which lies a given interval away from a root note.

*from* - The `TeoriaNote` which is the root of the measuring

*to* - An interval in "simple-format" such as 'M2' for
major second, and 'P5' for perfect fifth.

*direction* - An optional direction string, either `'up'` or `'down'`. Defaults to `'up'`
*to* - A `TeoriaInterval`

#### teoria.interval.between(from, to)
- Returns an interval object which represents the interval between two notes.
Expand All @@ -458,6 +452,9 @@ interval object would represent a minor third.
teoria.interval.between(teoria.note("a"), teoria.note("c'")) -> teoria.interval('m3')
```

#### teoria.interval.toCoord(simpleInterval)
- Returns a `TeoriaInterval` representing the interval expressed in string form.

#### teoria.interval.invert(simpleInterval)
- Returns the inversion of the interval provided

Expand All @@ -476,21 +473,34 @@ 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.

## TeoriaInterval(intervalNumber, quality[, direction])
## TeoriaInterval(coord)
- A representation of a music interval

#### TeoriaInterval.interval
#### TeoriaInterval.coord
- The interval representation of the interval

#### TeoriaInterval.number()
- The interval number (A ninth = 9, A seventh = 7, fifteenth = 15)

#### TeoriaInterval.simpleIntervalType
- The type of interval (mostly used internally)
#### TeoriaInterval.value()
- The value of the interval - That is a ninth = 9, but a downwards ninth is = -9

#### TeoriaInterval.base()
- Returns the name of the simple interval (not compound)

#### TeoriaInterval.quality
- The quality of the interval (`'diminished'`, `'minor'`, `'perfect'`, `'major'`
or `'augmented'`)
#### TeoriaInterval.type()
- Returns the type of array, either `'perfect'` (1, 4, 5, 8) or `'minor'` (2, 3, 6, 7)

#### TeoriaInterval.direction
- The direction of the interval (defaults to `'up'`)
#### TeoriaInterval.quality([long])
- The quality of the interval (`'dd'`, `'d'` `'m'`, `'p'`, `'M'`, `'A'` or `'AA'`)

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

#### TeoriaInterval.direction([newDirection])
- The direction of the interval

*newDirection* - If supplied, then the interval's direction is changed

#### TeoriaInterval#semitones()
- Returns the `number` of semitones the interval span.
Expand Down Expand Up @@ -523,6 +533,9 @@ teoria.interval('m23').compound() === 'm23'
teoria.interval('P5').compound() === 'P5'
```

#### TeoriaInterval#octaves()
- Returns the number of compound intervals

#### TeoriaInterval#isCompound()
- Returns a boolean value, showing if the interval is a compound interval

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "teoria",
"version": "0.2.3",
"version": "0.3.0",
"description": "Music theory for JavaScript",
"homepage": "http://saebekassebil.github.com/teoria",
"keywords": ["music", "theory", "jazz", "classical", "chord"],
Expand Down
54 changes: 23 additions & 31 deletions src/chord.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
function TeoriaChord(root, name) {
if (!(root instanceof TeoriaNote)) {
return null;
}

name = name || '';
this.name = root.name.toUpperCase() + root.accidental.sign + name;
this.name = root.name().toUpperCase() + root.accidental() + name;
this.symbol = name;
this.root = root;
this.intervals = [];
Expand Down Expand Up @@ -220,26 +216,22 @@ function TeoriaChord(root, name) {
}

if (bass) {
var intervals = this.intervals, bassInterval, inserted = 0, note;
var intervals = this.intervals, bassInterval, note;
// Make sure the bass is atop of the root note
note = teoria.note(bass + (root.octave + 1));
note = teoria.note(bass + (root.octave() + 1));

bassInterval = teoria.interval.between(root, note);
bass = bassInterval.simpleInterval;
bass = bassInterval.simple();

if (bassInterval.direction === 'up') {
bassInterval = bassInterval.invert();
bassInterval.direction = 'down';
}
bassInterval = bassInterval.invert();
bassInterval.direction('down');

this._voicing = [bassInterval];
for (i = 0; i < length; i++) {
if (intervals[i].interval === bass) {
if (intervals[i].simple() === bass)
continue;
}

inserted++;
this._voicing[inserted] = intervals[i];
this._voicing.push(intervals[i]);
}
}
}
Expand Down Expand Up @@ -304,11 +296,11 @@ TeoriaChord.prototype = {
var third, fifth, seventh, intervals = this.intervals;

for (var i = 0, length = intervals.length; i < length; i++) {
if (intervals[i].interval === 3) {
if (intervals[i].number() === 3) {
third = intervals[i];
} else if (intervals[i].interval === 5) {
} else if (intervals[i].number() === 5) {
fifth = intervals[i];
} else if (intervals[i].interval === 7) {
} else if (intervals[i].number() === 7) {
seventh = intervals[i];
}
}
Expand All @@ -317,7 +309,7 @@ TeoriaChord.prototype = {
return;
}

third = (third.direction === 'down') ? third.invert() : third;
third = (third.direction() === 'down') ? third.invert() : third;
third = third.simple();

if (fifth) {
Expand Down Expand Up @@ -359,10 +351,10 @@ TeoriaChord.prototype = {
for (i = 0; i < length; i++) {
interval = this.intervals[i];
invert = interval.invert();
if (interval.simpleIntervalType.name in has) {
has[interval.simpleIntervalType.name] = true;
} else if (invert.simpleIntervalType.name in has) {
has[invert.simpleIntervalType.name] = true;
if (interval.base() in has) {
has[interval.base()] = true;
} else if (invert.base() in has) {
has[invert.base()] = true;
}
}

Expand All @@ -372,10 +364,10 @@ TeoriaChord.prototype = {
for (i = 0; i < length; i++) {
interval = this.intervals[i];
invert = interval.invert();
if (interval.simpleIntervalType.name in has) {
has[interval.simpleIntervalType.name] = true;
} else if (invert.simpleIntervalType.name in has) {
has[invert.simpleIntervalType.name] = true;
if (interval.base() in has) {
has[interval.base()] = true;
} else if (invert.base() in has) {
has[invert.base()] = true;
}
}

Expand All @@ -393,7 +385,7 @@ TeoriaChord.prototype = {

interval = kStepNumber[interval];
for (i = 0, length = intervals.length; i < length; i++) {
if (intervals[i].interval === interval) {
if (intervals[i].number() === interval) {
return teoria.interval.from(this.root, intervals[i]);
}
}
Expand All @@ -411,8 +403,8 @@ TeoriaChord.prototype = {

transpose: function(interval, direction) {
this.root.transpose(interval, direction);
this.name = this.root.name.toUpperCase() +
this.root.accidental.sign + this.symbol;
this.name = this.root.name().toUpperCase() +
this.root.accidental() + this.symbol;

return this;
},
Expand Down
Loading

0 comments on commit 8c029dc

Please sign in to comment.