saebekassebil / teoria

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

Teoria version 0.2 - Chord voicings #34

Closed saebekassebil closed 11 years ago

saebekassebil commented 11 years ago

Hey guys, here's something I've wanted to add to the library for a long time, but hadn't really thought out.

This PR makes TeoriaChord more note-agnostic (as the internal representation is changed from absolute notes, to intervals, relative to the root), and makes it possible to voice chords!

var bbmaj = teoria.chord('Bbmaj7');
bbmaj.notes().toString(); // #-> 'bb4, d5, f5, a5'

// Change to voicing (to a delicious maj7 voicing):
bbmaj.voicing(['P1' ,'P5', 'M7', 'M10']);
bbmaj.notes().toString(); // 'bb4, f5, a5, d6'

// Reset the voicing to default (stacked in thirds):
bbmaj.resetVoicing();

This works, by having each TeoriaChord instance save two arrays: One for all the notes, which the chord includes (called intervals), and one which only saves the voicing, which can omit any note it wants (this is called pt. _voicing).

Only problem is: It brakes the API. Before TeoriaChord.notes was a property, now it's method. This is why I've bumped the version number to 0.2.0. Another thing is that it's possible to add intervals to the voicing which aren't part of the chord. Fx:

var cm7 = teoria.chord('Cm7');
cm7.notes().toString();  // #-> 'c4, eb4, g4, bb4'

// This is a Cm9 with no root:
cm7.voicing(['M2', 'm3', 'P5', 'm7']);
cm7.notes.toString();  // #-> 'd4, eb4, g4, bb4'

So as you can see, it's possible to add a ninth in the voicing, although it isn't part of the original chord. I think this makes sense, as this is often seen in Jazz (putting 11th and 9th whereever you want), but I'm note sure that this is "technically" correct.

One other thing I'd like to discuss is how the notes() and voicing() method differ. Right now, calling voicing() with no arguments, just returns the current voicing. Maybe it should change so notes() always return all the notes of the chord. and voicing() instead returns the notes in the voicing?

I'm really excited about this change, and hope some of you guys will try it out, as I see a lot of potential in this feature (and especially, when using this along with something like #32 !).

quickredfox commented 11 years ago

:+1: