I've two snippets below, the first one output all the keys of a piano and the second one give me a scale when given a starting note. For those who don't know how a piano is structured here is an image of a piano.
Basically I want to put each notes, in an ordered array. As you can see the black notes have two names, one with b
in it and one with #
. Those two names are equivalent but I'm using the one with b
.
So I have to create this array (like the image):
[ "A0", "Bb0", "B0", "C1", "Db1", "D1", "Eb1", "E1", "F1", "Gb1", "G1", "Ab1", "A1", "Bb1", "B1".............., "B7", "C8"]
Or check the console output from the jsfiddle below.
const KEYS_NORMAL = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"];
let keys = KEYS_NORMAL.slice(-3);
keys = keys.map( k => k + '0');
for(let octave = 1; octave < 8; octave++){
for(let key of KEYS_NORMAL){
keys.push(key + octave)
}
}
keys.push('C8')
keys.forEach(k => console.log(k));
// I'm actually doing some work with those notes, So ultimately this is one more loop.
The second algorithm returns a scale given a note. For those who don't know a scale starts on any note and is given by the algorithm below:
Major: 2 - 2 - 1 - 2 - 2 - 2 - 1
Minor : 2 - 1 - 2 - 2 - 1 - 2 - 2
We can distinguish between major and minor because an m
is appended to the name, eg: A
is major whereas Am
is minor.
Where 1 means go one note above, and 2 means go 2 notes above (the black keys are also notes).
Code :
majorSemiTones = [2,2,1,2,2,2];
minorSemiTones = [2,1,2,2,1,2];
KEYS = ["A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab"];
KEYS_NORMALIZED = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"];
function getScale(scaleName){
let tonic = scaleName.replace("m", "");
let keys = [];
let minor = false;
let scaleIndex;
let intervals = this.majorSemiTones;
if(scaleName.indexOf("m") > -1){
minor = true;
intervals = this.minorSemiTones;
}
scaleIndex = KEYS.indexOf(tonic);// starts on the tonic
for(let i = 0; i < 7; i++){
keys.push(KEYS[scaleIndex]);
if( scaleIndex + intervals[i] > KEYS.length - 1 ){
scaleIndex = scaleIndex + intervals[i] - KEYS.length;
}else{
scaleIndex += intervals[i];
}
}
return keys;
}
What I hope to get from this review is ways to improve my code. The second snippet seems needlessly complex and unreadable while the first one seems inefficient and seems like it could benefit from some functional js.