From e5a2c724a7edaaf1d280de4c1c7fc71d3208f7de Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 19 Sep 2015 23:20:01 -0400 Subject: [PATCH 1/5] Add signature method for a scale. Closes #89 --- README.md | 5 +++++ lib/scale.js | 31 +++++++++++++++++++++++++++++++ test/scales.js | 12 ++++++++++++ 3 files changed, 48 insertions(+) diff --git a/README.md b/README.md index 9f2732e..00d7bdf 100755 --- a/README.md +++ b/README.md @@ -181,6 +181,8 @@ 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); +Returns a new note based on the passed interval. + Look at the documentation for `teoria.interval` #### Note#transpose(interval) @@ -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..f9da304 100644 --- a/lib/scale.js +++ b/lib/scale.js @@ -102,6 +102,37 @@ 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 offset = this.tonic.coord[1]; + + 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; + }); + + //if at least one flat - return flats signature + if (sequence.some(function (note) { + return note.accidentalValue() < 0; + })) { + return sequence.reverse().filter(function (note) { + return note.accidentalValue() !== 0; + }); + } + else { + 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); From f1b9974adaab60a5a90a04072b3f6828bab52cb6 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 19 Sep 2015 23:29:01 -0400 Subject: [PATCH 2/5] Remove unnecessary line --- lib/scale.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/scale.js b/lib/scale.js index f9da304..960696b 100644 --- a/lib/scale.js +++ b/lib/scale.js @@ -112,8 +112,6 @@ Scale.prototype = { * 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 offset = this.tonic.coord[1]; - 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]; From b92b0ac3dc2f037d55a7e82f18d1838d7ea375a1 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 19 Sep 2015 23:31:11 -0400 Subject: [PATCH 3/5] Remove duplicating code --- lib/scale.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/scale.js b/lib/scale.js index 960696b..7d32ad2 100644 --- a/lib/scale.js +++ b/lib/scale.js @@ -122,15 +122,12 @@ Scale.prototype = { if (sequence.some(function (note) { return note.accidentalValue() < 0; })) { - return sequence.reverse().filter(function (note) { - return note.accidentalValue() !== 0; - }); - } - else { - return sequence.filter(function (note) { - return note.accidentalValue() !== 0; - }); + sequence = sequence.reverse(); } + + return sequence.filter(function (note) { + return note.accidentalValue() !== 0; + }); } }; From 73d7bd3ac3a873f2761685453cfec2a93f92a3e7 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 24 Sep 2015 08:01:14 -0400 Subject: [PATCH 4/5] Remove extra comment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 00d7bdf..34c2c2e 100755 --- a/README.md +++ b/README.md @@ -181,10 +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); -Returns a new note based on the passed interval. Look at the documentation for `teoria.interval` + #### Note#transpose(interval) - Like the `#interval` method, but changes `this` note, instead of returning a new From c9ac2a388ce408356e2c771dbc58d74bdfd167fa Mon Sep 17 00:00:00 2001 From: Dmitry Date: Thu, 24 Sep 2015 08:11:06 -0400 Subject: [PATCH 5/5] Increase descriptivity --- lib/scale.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/scale.js b/lib/scale.js index 7d32ad2..e03765f 100644 --- a/lib/scale.js +++ b/lib/scale.js @@ -118,10 +118,11 @@ Scale.prototype = { return aCoord - bCoord; }); - //if at least one flat - return flats signature - if (sequence.some(function (note) { + var hasFlat = sequence.some(function (note) { return note.accidentalValue() < 0; - })) { + }); + + if (hasFlat) { sequence = sequence.reverse(); }