http://qs321.pair.com?node_id=890443


in reply to Re^2: Transpose guitar chords
in thread Transpose guitar chords

Good point. You are right that the code above is only for major keys.

Minor keys are a bit more complex though than "reverse the use of sharps and flats". For the minor scales, only D,G switch from flats to sharps. F and all flat keys (Ab,Bb, etc) uses flats in both major and minor modes. B,E and all sharp keys (A#,B#,etc) use sharps for both major and minor modes. A goes from sharps to all naturals, and C goes from all naturals to flats. See Key signature.

So here is the script revised to take into account minor keys as well as major keys (changes marked with <== ):

use strict; use warnings; my %Tone =( A => 0, B => 2, C => 3, D => 5, E => 7, F => 8, G=>10); my @Notes; foreach my $natural ('A'..'G') { my $i = $Tone{$natural}; my $iFlat = $i ? $i-1 : 11; $Tone{$natural.'#'} = $i+1; $Tone{$natural.'b'} = $iFlat; $Notes[$iFlat][0]=$natural.'b'; $Notes[$i][0] = $natural; $Notes[$i][1] = $natural; $Notes[$i+1][1]=$natural.'#'; } #print "Tone: ". Dumper(\%Tone); #print "Notes: ". Dumper(\@Notes); sub transpose { my ($key, $aChord, $toKey) = @_; my @aTransposed; my $bMinor = $key =~ /m$/ ? 1 : 0; # <== $key= $key =~ /^(.*)m$/ ? $1 : $key; # <== $toKey= $toKey =~ /^(.*)m$/ ? $1 : $toKey; # <== my $iShift = $Tone{$toKey} - $Tone{$key}; my $iIndex = $bMinor # <== ? ($toKey =~ /^(?:C|D|F|G|.b)$/ ? 0 : 1) # minor key : ($toKey =~ /^(?:F|.b)$/ ? 0 : 1); # F uses flats in major push @aTransposed, $Notes[($Tone{$_}+$iShift) % 12][$iIndex] for @$aChord; return \@aTransposed; } # demo local $"='-'; print "Major modes\n"; for ('A'..'G','Eb','Bb', 'D', 'E') { print "C-E-G => $_ : @{transpose('C',[qw(C E G)],$_)}\n"; } print "Minor modes\n"; for ('A'..'G','Eb','Bb', 'D', 'E') { print "C-Eb-G => $_ : @{transpose('Cm',[qw(C Eb G)],qq{${_}m})}\n"; } # outputs Major modes C-E-G => A : A-C#-E C-E-G => B : B-D#-F# C-E-G => C : C-E-G C-E-G => D : D-F#-A C-E-G => E : E-G#-B C-E-G => F : F-A-C C-E-G => G : G-B-D C-E-G => Eb : Eb-G-Bb C-E-G => Bb : Bb-D-F C-E-G => D : D-F#-A C-E-G => E : E-G#-B Minor modes C-Eb-G => A : A-C-E C-Eb-G => B : B-D-F# C-Eb-G => C : C-Eb-G C-Eb-G => D : D-F-A C-Eb-G => E : E-G-B C-Eb-G => F : F-Ab-C C-Eb-G => G : G-Bb-D C-Eb-G => Eb : Eb-Gb-Bb C-Eb-G => Bb : Bb-Db-F C-Eb-G => D : D-F-A C-Eb-G => E : E-G-B

And should anyone else see room for improvement, please post!

Replies are listed 'Best First'.
Re^4: Transpose guitar chords
by Anonymous Monk on Feb 28, 2011 at 01:22 UTC
    Right, sorry, I should have said, sometimes reverse the use of sharps and flats. Another nice improvement would be to handle chord names in full generality, including minor chords, augmented, diminished, etc . This is mostly a matter of allowing suffixes after the sharp or flat notation, in the typical form, e.g. G sharp minor half diminished seventh is G#m7(b5). I think you'd just have to take everything after the A-G(#|b)? and just carry it through the transposition.