Create a function for transposing musical chords

5

2

Your mission is to create a function for transposing music chords.

Copied from SO with permission of the original asker, I just really wanted to see what you guys could do with this one:

Since I don't expect everyone to be a musician here, I'll try to explain how it works in music theory. I hope I don't forget something. If yes, musicians, please, correct me.

1) The simple chords

The simple chords are almost as simple as an alphabet and it goes like this:

C, C#, D, D#, E, F, F#, G, G#, A, A# B

From B it loops all over again to C. Therefore, If the original chord is E and we want to transpose +1, the resulting chord is F. If we transpose +4, the resulting chord is G#.

2) Expanded chords

They work almost like the simple chords, but contain a few more characters, which can safely be ignored when transposing. For example:

Cmi, C#7, Dsus7, Emi, Fsus4, F#mi, G ...

So again, as with the simple chords, if we transpose Dsus7 + 3 = Fsus7

3) Non-root bass tone

A problem arises when the bass plays a different tone than the chord root tone. This is marked by a slash after the chord and also needs to be transposed. Examples:

C/G, Dmi/A, F#sus7/A#

As with examples 1 and 2, everything is the same, but the part after the slash needs transpose too, therefore:

C/G + 5 = F/C

F#sus7/A# + 1 = Gsus7/B

I think this should be all, unless I forgot something.

So basically, imagine you have a javascript variable called chord and the transpose value transpose. What code would transpose the chord?

Example:

var chord = 'F#sus7/C#';
var transpose = 3; // remember this value also may be negative, like "-4"
... code here ...
var result; // expected result = 'Asus7/E';

original question here: https://stackoverflow.com/questions/7936843/how-do-i-transpose-music-chords-using-javascript (note that he's asking for JS, for this challenge I don't care what language its in)

kekekela

Posted 2011-10-29T04:07:33.640

Reputation: 153

Answers

2

Haskell, 146

c=zip(words"C C# D D# E F F# G G# A A# B")[0..]
x#n=maybe x(\i->fst$c!!mod(i+n)12)$lookup x c
(x:'#':y)%n=(x:"#")#n++y%n
(x:y)%n=[x]#n++y%n
x%_=x

This defines an operator % that transposes a chord by a given amount, so you'd use it like this:

*Main> "E"%1
"F"
*Main> "E"%4
"G#"
*Main> "Dsus7"%3
"Fsus7"
*Main> "C/G"%5
"F/C"
*Main> "F#sus7/A#"%1
"Gsus7/B"

hammar

Posted 2011-10-29T04:07:33.640

Reputation: 4 011

2

OK, within the limitations of the question as asked and not catering for a lot of things you'd need to allow for if using with real music (flats being the most obvious):

function t(c,a) {
  var s=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],i;
  return c.replace(/[A-G]#?/g,function(m){return s[(i=(s.indexOf(m)+a)%s.length)<0?i+s.length:i];});
}

This is my first attempt at code-golf, so I hope I've taken the right approach. Following is the readable version that I originally posted at stackoverflow.com:

function transposeChord(chord, amount) {
  var scale = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
  return chord.replace(/[CDEFGAB]#?/g,
                       function(match) {
                         var i = (scale.indexOf(match) + amount) % scale.length;
                         return scale[ i < 0 ? i + scale.length : i ];
                       });
}

nnnnnn

Posted 2011-10-29T04:07:33.640

Reputation: 121

I think flats and stuff like E# etc isn't really useful when simply "sharing" chords with friends and playing music this way. Of course they are very important in sheet music etc, but for people transposing music to play for their own pleasure, this seems like a very satisfying solution. +1 – Richard Rodriguez – 2011-10-29T04:46:33.403

@RIMMER - Even with a simple chord chart I find it much harder to follow when the author has ignored flats. Do you never play in the key of F (which has a Bb, not an A#)? I'd like to see a full solution (using my function or not) that transposes a whole chord chart and not just one chord. Thanks for the up-vote. – nnnnnn – 2011-10-29T04:56:30.303

Oh OK, I see what you mean now. Well, I play the piano and I know the scales perfectly, so even if the chords say A# and I'm in the F scale, I always know that I can play A in that scale and that the A# notation is actually Bb. Anyway, maybe you can re-define the problem to consider all this in the equation? I don't know how to explain the whole theory to reach the full solution, but I'd be happy to see the code! – Richard Rodriguez – 2011-10-29T05:07:58.043

A full solution is beyond me (and would probably be incomprehensible in a code-golf setting). I agree that yes, if I see an A# chord in the key of F I know that it should be a Bb, but it's a distraction so I'd rather correct the chart before I play from it. – nnnnnn – 2011-10-29T05:34:53.610

If I write down all the chords and exactly specify which scale has what sharps and what flats and would offer you a money reward, how much would it cost to code the full solution? (this is rather a reply for your stackoverflow comment, but I didn't want to put it there). anyway, my mail is rimmer@rimmer.sk ... – Richard Rodriguez – 2011-10-29T05:37:17.007

I'm not sure how long it would take to write a solution that would satisfy me, certainly much longer than it would take me to just transpose manually whenever I happen to need it. I'd suggest extending the above function to accept another parameter for whether to use sharps or flats for the output key, and to look for sharps and flats in the input, and you'd probably be most of the way there for most normal cases - probably wouldn't take too long to get that far. Then just manually double-check the output for edge cases. – nnnnnn – 2011-10-29T10:01:42.927

P.S. Google found a few websites that offer transposition on a par with what I coded above, some of which also show guitar chord fingerboard diagrams for the appropriate key, e.g.: http://www.transposechords.com/ and http://www.chordie.com.

– nnnnnn – 2011-10-29T10:04:07.337

I've got 186 as the count for this solution, please let me know if I got it wrong. – kekekela – 2011-10-31T00:53:17.133

0

As a preliminary effort, I'd like to flesh-out some of what "the full solution" should take into account.

Sharps and Flats

When transposing a musical key, one adds sharps or flats to the key signature according to the distance traversed in the "circle of fourths" (or fifths, depending on the direction you're going).

fifths from C up to the enharmonic
key: C G  D  A  E  B  F# C# G#  D#  A#  E#  B#
add:   F# C# G# D# A# E# B# F## C## G## D## A##

fourths from C down to the enharmonic
key: C F  Bb Eb Ab Db Gb Cb Fb  Bbb Ebb Abb Dbb
add:   Bb Eb Ab Db Gb Cb Fb Bbb Ebb Abb Dbb Gbb

So the key of C can be written with zero sharps or flats, or with twelve sharps, or with twelve flats. The first options is clearly superior.

But we only really need the middle of the table above because all those double-sharps and double-flats mean that some note is being given an overly-complicated name. So extracting the middle and arranging in sequence gives us this list of keys.

C  Db(5 'b's) D(2#) Eb(3b) E(4#) F(1b) F#(6#)[or Gb(6b)]
G(1#) Ab(4b) A(3#) Bb(2b) B(5#) C

And, dropping the counts and picking between F# and Gb (all flats looks prettier than one lonely sharp) gives:

C Db D Eb F Gb G Ab A Bb B C

But for named chords, the situation is less clear because the names carry accidentals with them.

luser droog

Posted 2011-10-29T04:07:33.640

Reputation: 4 535