Perl: the Markov chain saw PerlMonks

### Re^3: Transpose guitar chords

by ELISHEVA (Prior)
 on Feb 27, 2011 at 18:58 UTC ( #890443=note: print w/replies, xml ) Need Help??

in reply to Re^2: 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.

Create A New User
Node Status?
node history
Node Type: note [id://890443]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (16)
As of 2016-10-26 13:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
How many different varieties (color, size, etc) of socks do you have in your sock drawer?

Results (340 votes). Check out past polls.