diff --git a/README.md b/README.md index 9f2732e..34c2c2e 100755 --- a/README.md +++ b/README.md @@ -181,8 +181,10 @@ The chroma number is ranging from pitch class C which is 0 to 11 which is B #### Note#interval(interval) - A sugar function for calling teoria.interval(note, interval); + Look at the documentation for `teoria.interval` + #### Note#transpose(interval) - Like the `#interval` method, but changes `this` note, instead of returning a new @@ -415,6 +417,9 @@ scale step. E.g. 'first', 'second', 'fourth', 'seventh'. *showOctaves* - A boolean meaning the same as `showOctaves` in `Note#solfege` +#### Scale#signature() + - Returns the sequence of notes representing the key signature of a scale + ## teoria.interval(from, to) - A sugar function for the `#from` and `#between` methods of the same namespace and diff --git a/lib/scale.js b/lib/scale.js index 90b9f1d..e03765f 100644 --- a/lib/scale.js +++ b/lib/scale.js @@ -102,6 +102,33 @@ Scale.prototype = { this.tonic = scale.tonic; return this; + }, + + /** + * Get the sequence of notes representing key signature of a scale, in proper order. + * There are two possible signatures for any scale: flats and sharps. + * Sharps signature is got by traversing notes by P5 intervals to the right + * till all the notes of the scale are covered. + * Flats signature is got by traversing by P4 intervals to the left in the same manner, which is equal to reversed sharps. + */ + signature: function() { + var sequence = this.notes().sort(function (a, b) { + var aCoord = a.coord[1] < 0 ? a.coord[1] + 12 : a.coord[1]; + var bCoord = b.coord[1] < 0 ? b.coord[1] + 12 : b.coord[1]; + return aCoord - bCoord; + }); + + var hasFlat = sequence.some(function (note) { + return note.accidentalValue() < 0; + }); + + if (hasFlat) { + sequence = sequence.reverse(); + } + + return sequence.filter(function (note) { + return note.accidentalValue() !== 0; + }); } }; diff --git a/test/scales.js b/test/scales.js index 0bcc819..36baff2 100644 --- a/test/scales.js +++ b/test/scales.js @@ -57,6 +57,18 @@ vows.describe('Scales').addBatch({ assert.deepEqual(note.scale('chromatic').simple(), ["ab", "bbb", "bb", "cb", "c", "db", "d", "eb", "fb", "f", "gb", "g"]); + }, + + 'Signature': function(note) { + function name (note) {return note.name() + note.accidental() } + + assert.equal(teoria.note('f#').scale('major').signature().map(name).toString(), 'f#,c#,g#,d#,a#,e#'); + assert.equal(teoria.note('db').scale('major').signature().map(name).toString(), 'bb,eb,ab,db,gb'); + + assert.equal(teoria.note('c').scale('major').signature().map(name).toString(), ''); + assert.equal(teoria.note('a').scale('minor').signature().map(name).toString(), ''); + assert.equal(teoria.note('d').scale('major').signature().map(name).toString(), 'f#,c#'); + assert.equal(teoria.note('b').scale('minor').signature().map(name).toString(), 'f#,c#'); } } }).export(module);