line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Music::Chord::Namer; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
51623
|
use 5.008007; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
1662
|
|
4
|
1
|
|
|
1
|
|
8
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
41
|
|
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
45
|
|
6
|
1
|
|
|
1
|
|
2876
|
use subs qw/jws jwn/; |
|
1
|
|
|
|
|
23
|
|
|
1
|
|
|
|
|
6
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
require Exporter; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
13
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
14
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# This allows declaration use Music::Chord::Namer ':all'; |
17
|
|
|
|
|
|
|
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK |
18
|
|
|
|
|
|
|
# will save memory. |
19
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw( |
20
|
|
|
|
|
|
|
chordname |
21
|
|
|
|
|
|
|
) ] ); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
our @EXPORT = qw( |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
our %NOTES; |
33
|
|
|
|
|
|
|
our $NAME; |
34
|
|
|
|
|
|
|
our $D; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub chordname { # the sub that guesses the name of the chord |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# convert note names to numbers |
40
|
8
|
|
|
8
|
1
|
5377
|
my %notevalues = ('C'=>0,'C#'=>1,'Db'=>1,'D'=>2,'D#'=>3,'Eb'=>3,'E'=>4,'F'=>5, |
41
|
|
|
|
|
|
|
'F#'=>6,'Gb'=>6,'G'=>7,'G#'=>8,'Ab'=>8,'A'=>9,'A#'=>10,'Bb'=>10,'B'=>11); |
42
|
|
|
|
|
|
|
# convert note numbers back to names |
43
|
8
|
|
|
|
|
33
|
my @value2note = ('C','C#','D','D#','E','F','F#','G','G#','A','A#','B'); |
44
|
|
|
|
|
|
|
|
45
|
8
|
|
|
|
|
13
|
my @notes = (); # store notes here... |
46
|
|
|
|
|
|
|
|
47
|
8
|
50
|
|
|
|
29
|
if(@_ > 1){ # if the notes are supplied as a list |
|
|
50
|
|
|
|
|
|
48
|
0
|
|
|
|
|
0
|
@notes = @_; # ok |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
elsif($_[0]) { # or as a string |
51
|
8
|
|
|
|
|
36
|
@notes = split(/\s+/, $_[0]); # deal with it! |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
else { |
54
|
0
|
|
|
|
|
0
|
return; # no notes?? |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
8
|
|
|
|
|
14
|
my @notenumbers = (); # store the corresponding numbers here |
58
|
8
|
|
|
|
|
19
|
foreach my $note(@notes){ |
59
|
38
|
50
|
|
|
|
99
|
die "Bad note \"$note\"!" unless defined $notevalues{$note}; |
60
|
38
|
|
|
|
|
60
|
my $notenumber = $notevalues{$note}; |
61
|
|
|
|
|
|
|
# make sure that it's a higher number than that of the note that preceeded it... |
62
|
38
|
100
|
|
|
|
71
|
if(defined $notenumbers[$#notenumbers]){ |
63
|
30
|
|
|
|
|
63
|
while($notenumber < $notenumbers[$#notenumbers]){ $notenumber += 12; } |
|
9
|
|
|
|
|
19
|
|
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
# add it to the list |
66
|
38
|
|
|
|
|
62
|
push @notenumbers, $notenumber; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# Naming |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# We need to make some decisions about what to call it a chord... |
74
|
|
|
|
|
|
|
# Lets assume we know no better and we're going to try every possible chord |
75
|
|
|
|
|
|
|
# and see which name is the shortest! |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Lets go through every probable root note first... one of the two bass notes must |
78
|
|
|
|
|
|
|
# be the 1, m3, 3, 5 or m7 of the chord. No cheating! |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# We can then work out the names of these 10 chords... |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# 1) The bass note is 1 |
83
|
|
|
|
|
|
|
# 2) The bass note is m3 |
84
|
|
|
|
|
|
|
# 3) The bass note is 3 |
85
|
|
|
|
|
|
|
# 4) The bass note is 5 |
86
|
|
|
|
|
|
|
# 5) The bass note is m7 |
87
|
|
|
|
|
|
|
# 6) The bass note is separate, the next note is 1 |
88
|
|
|
|
|
|
|
# 7) The bass note is separate, the next note is m3 |
89
|
|
|
|
|
|
|
# 8) The bass note is separate, the next note is 3 |
90
|
|
|
|
|
|
|
# 9) The bass note is separate, the next note is 5 |
91
|
|
|
|
|
|
|
# 10) The bass note is separate, the next note is m7 |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# notes set to bass note being a certain chord member |
94
|
|
|
|
|
|
|
|
95
|
8
|
|
|
|
|
12
|
my @inversions = (); |
96
|
|
|
|
|
|
|
# name, notes, split, comment |
97
|
|
|
|
|
|
|
# the name depends on what we're saying the bass note is... it could be the root, minor or major 3rd |
98
|
|
|
|
|
|
|
# 5th or minor 7th. |
99
|
38
|
|
|
|
|
102
|
push @inversions, |
100
|
38
|
|
|
|
|
83
|
{name => $value2note[($notevalues{$notes[0]}) % 12], notes => [map { $_ - $notenumbers[0] } @notenumbers], split => '', comment => 'bass 1'}, |
101
|
38
|
|
|
|
|
98
|
{name => $value2note[($notevalues{$notes[0]} - 3) % 12], notes => [map { $_ - $notenumbers[0] + 3 } @notenumbers], split => $notes[0], comment => 'bass m3'}, |
102
|
38
|
|
|
|
|
77
|
{name => $value2note[($notevalues{$notes[0]} - 4) % 12], notes => [map { $_ - $notenumbers[0] + 4 } @notenumbers], split => $notes[0], comment => 'bass 3'}, |
103
|
38
|
|
|
|
|
68
|
{name => $value2note[($notevalues{$notes[0]} + 5) % 12], notes => [map { $_ - $notenumbers[0] - 5 } @notenumbers], split => $notes[0], comment => 'bass 5'}, |
104
|
8
|
|
|
|
|
42
|
{name => $value2note[($notevalues{$notes[0]} + 2) % 12], notes => [map { $_ - $notenumbers[0] - 2 } @notenumbers], split => $notes[0], comment => 'bass m7'}; |
105
|
|
|
|
|
|
|
|
106
|
8
|
|
|
|
|
133
|
shift(@notenumbers); # get rid of bass note, incase it's a split! |
107
|
|
|
|
|
|
|
# ... and do it all again! |
108
|
30
|
|
|
|
|
72
|
push @inversions, |
109
|
30
|
|
|
|
|
81
|
{name => $value2note[($notevalues{$notes[0]}) % 12], notes => [map { $_ - $notenumbers[0] } @notenumbers], split => $notes[0], comment => 'split 1'}, |
110
|
30
|
|
|
|
|
67
|
{name => $value2note[($notevalues{$notes[0]} - 3) % 12], notes => [map { $_ - $notenumbers[0] + 3 } @notenumbers], split => $notes[0], comment => 'split m3'}, |
111
|
30
|
|
|
|
|
133
|
{name => $value2note[($notevalues{$notes[0]} - 4) % 12], notes => [map { $_ - $notenumbers[0] + 4 } @notenumbers], split => $notes[0], comment => 'split 3'}, |
112
|
30
|
|
|
|
|
65
|
{name => $value2note[($notevalues{$notes[0]} + 5) % 12], notes => [map { $_ - $notenumbers[0] - 5 } @notenumbers], split => $notes[0], comment => 'split 5'}, |
113
|
8
|
|
|
|
|
21
|
{name => $value2note[($notevalues{$notes[0]} + 2) % 12], notes => [map { $_ - $notenumbers[0] - 2 } @notenumbers], split => $notes[0], comment => 'split m7'}; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# ok, here's how it works: |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# There are these notes: |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# 0 1 2 3 4 5 6 7 8 9 10 11 |
120
|
|
|
|
|
|
|
# 1 b2 2 m3 3 4 b5 5 a5 6 m7 7 |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# 12 13 14 15 16 17 18 19 20 21 22 23 |
123
|
|
|
|
|
|
|
# 8 b9 9 m10 10 11 b12 12 b13 13 m14 14 |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# these are the names of the notes we could have in the chord |
126
|
8
|
|
|
|
|
45
|
my @valuenames = qw( |
127
|
|
|
|
|
|
|
1 b2 2 m3 3 4 b5 5 a5 6 m7 7 |
128
|
|
|
|
|
|
|
8 b9 9 m10 10 11 b12 12 b13 13 m14 14); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# Chord folding |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# We'll fold our chord into this structure... whichever note is the root can get |
133
|
|
|
|
|
|
|
# set as 0. Any note below it can have 12 added to it until it's above 0. Any |
134
|
|
|
|
|
|
|
# note above 23 can have 12 taken from it until it is 23 or less. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# fold each of our inversions of the chord! |
137
|
8
|
|
|
|
|
12
|
foreach my $hash(@inversions){ |
138
|
80
|
|
|
|
|
93
|
my $array = $hash->{notes} ; |
139
|
80
|
|
|
|
|
141
|
for(my $i = 0; $i< @$array; $i++){ |
140
|
340
|
|
|
|
|
611
|
while($array->[$i] > 23){ $array->[$i] -= 12; } # anything over 23, drop it an octave |
|
2
|
|
|
|
|
73
|
|
141
|
340
|
|
|
|
|
839
|
while($array->[$i] < 0){ $array->[$i] += 12; } # anything under 0, raise it an octave |
|
48
|
|
|
|
|
114
|
|
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# we'll put the chord names in here: |
146
|
8
|
|
|
|
|
12
|
my @NAMES = (); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# now we need to turn them into hashes!!! We'll do all the rest for each hash |
149
|
8
|
|
|
|
|
13
|
foreach my $hash(@inversions){ |
150
|
|
|
|
|
|
|
# skip it if the name is the same as the split... this could happen in the "next" inversions... there's |
151
|
|
|
|
|
|
|
# no point to it because it will already have been covered by "bass 1" |
152
|
80
|
100
|
100
|
|
|
436
|
next if $hash->{'split'} && $notevalues{$hash->{'split'}} == $notevalues{$hash->{name}}; |
153
|
|
|
|
|
|
|
# the notes... |
154
|
72
|
|
|
|
|
97
|
my $array = $hash->{notes} ; |
155
|
72
|
|
|
|
|
213
|
%NOTES = (); # global, setting it up before calling isset, etc |
156
|
72
|
|
|
|
|
104
|
$NAME = $hash->{name}; # global |
157
|
72
|
|
|
|
|
171
|
for(my $i = 0; $i< @$array; $i++){ |
158
|
310
|
|
|
|
|
1058
|
$NOTES{$array->[$i]} = 1; # set up the existence of the notes in the hash |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Duplicate notes |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# If any note from 0-11 is set then the corresponding note from 12-23 can be |
164
|
|
|
|
|
|
|
# un-set. |
165
|
|
|
|
|
|
|
|
166
|
72
|
|
|
|
|
119
|
foreach (0..11){ # remove notes from upper octave that are already in lower one! |
167
|
864
|
100
|
|
|
|
1180
|
isset($_) and unset($_+12) |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# Shifting 1, 3, 5, 7 |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# If none of the 1sts, 3rds, 5ths or 7ths are set in the lower octave then any |
173
|
|
|
|
|
|
|
# corresponding notes in the upper octave can be shifted down. |
174
|
|
|
|
|
|
|
|
175
|
72
|
100
|
100
|
|
|
131
|
isset(0) or (unset(12) and set(0)); # drop 12 to 0 if 0 doesn't exist |
176
|
72
|
100
|
100
|
|
|
119
|
isset(3) or isset(4) # drop either 16 or 15 to 3 or 4 unless 3 or 4 is already set (3rds) |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
177
|
|
|
|
|
|
|
or (unset(4+12) and set(4)) or (unset(3+12) and set(3)); |
178
|
72
|
50
|
50
|
|
|
127
|
isset(6) or isset(7) or isset(8) # the same for 5ths |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
179
|
|
|
|
|
|
|
or (unset(7+12) and set(7)) or (unset(6+12) and set(6)) or (unset(8+12) and set(8)); |
180
|
72
|
50
|
50
|
|
|
116
|
isset(10) or isset(11) # and 7ths |
|
|
|
100
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
181
|
|
|
|
|
|
|
or (unset(10+12) and set(10)) or (unset(11+12) and set(11)); |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# Now, lets look at what we have... |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Is there a root note (0)??? if not, then add "no-root" to the name |
186
|
|
|
|
|
|
|
# Is there a third (3,4)??? if not, then add "no-3rd" to the name |
187
|
|
|
|
|
|
|
# etc... |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# (if the selection is true, the note concerned is removed so as not to be |
190
|
|
|
|
|
|
|
# evaluated more than once) |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Reasoning... |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# unset returns true if it was able to unset, false otherwise... |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# special chords: |
198
|
72
|
50
|
33
|
|
|
241
|
$D = lower_octave_is(0,3,6,9) and unset(0,3,6,9) and app('o7'); |
199
|
72
|
50
|
33
|
|
|
197
|
$D = $D || lower_octave_is(0,3,6,10) and unset(0,3,6,10) and app('Ø7'); |
|
|
|
33
|
|
|
|
|
200
|
72
|
100
|
66
|
|
|
183
|
$D = $D || lower_octave_is(0,3,6) and unset(0,3,6) and app('o'); |
|
|
|
66
|
|
|
|
|
201
|
|
|
|
|
|
|
# sort out our thirds |
202
|
72
|
100
|
100
|
|
|
187
|
$D or |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
203
|
|
|
|
|
|
|
unset(4) or |
204
|
|
|
|
|
|
|
(unset(3) and app('m')) or |
205
|
|
|
|
|
|
|
(unset(5) and app(' sus')) or |
206
|
|
|
|
|
|
|
(unset(2) and app(' sus2')) or |
207
|
|
|
|
|
|
|
app('no-3rd'); |
208
|
|
|
|
|
|
|
# sort out 13 11 9 7 |
209
|
72
|
50
|
100
|
|
|
126
|
(unset(21,17,14,10) and app('13')) or |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
210
|
|
|
|
|
|
|
(unset(21,17,14,11) and app('maj13')) or |
211
|
|
|
|
|
|
|
(unset(17,14,10) and app('11')) or |
212
|
|
|
|
|
|
|
(unset(17,14,11) and app('maj11')) or |
213
|
|
|
|
|
|
|
(unset(14,10) and app('9')) or |
214
|
|
|
|
|
|
|
(unset(14,11) and app('maj9')) or |
215
|
|
|
|
|
|
|
(unset(10) and app('7')) or |
216
|
|
|
|
|
|
|
(unset(11) and app('maj7')) or |
217
|
|
|
|
|
|
|
(unset(9,14) and app('6/9')) or |
218
|
|
|
|
|
|
|
(unset(9) and app('-6')); |
219
|
|
|
|
|
|
|
# sort out 5 |
220
|
72
|
100
|
100
|
|
|
207
|
$D or |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
221
|
|
|
|
|
|
|
unset(7) or |
222
|
|
|
|
|
|
|
(unset(6) and app(' b5')) or |
223
|
|
|
|
|
|
|
(unset(8) and app(' #5')) or |
224
|
|
|
|
|
|
|
app(' no5'); |
225
|
|
|
|
|
|
|
# root |
226
|
72
|
100
|
100
|
|
|
201
|
$D or |
227
|
|
|
|
|
|
|
unset(0) or app(' no-root'); |
228
|
|
|
|
|
|
|
# any additional notes |
229
|
72
|
|
|
|
|
106
|
foreach (0..23){ |
230
|
1728
|
100
|
|
|
|
2756
|
unset($_) and app(' add'.$valuenames[$_]); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
# split |
233
|
72
|
100
|
|
|
|
176
|
if($hash->{split}){ $NAME .= '/'.$hash->{split}; } |
|
64
|
|
|
|
|
119
|
|
234
|
72
|
|
|
|
|
166
|
push @NAMES, $NAME; |
235
|
|
|
|
|
|
|
} |
236
|
8
|
|
|
|
|
68
|
my @results = sort {length($a) <=> length($b)} @NAMES; |
|
162
|
|
|
|
|
219
|
|
237
|
8
|
50
|
|
|
|
24
|
if(wantarray){ |
238
|
0
|
|
|
|
|
0
|
return @results; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
else { |
241
|
8
|
|
|
|
|
553
|
return $results[0]; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# some subs: |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub set { |
251
|
13
|
|
|
13
|
0
|
26
|
$NOTES{$_[0]} = 1; |
252
|
13
|
|
|
|
|
26
|
return 1; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
sub isset { |
255
|
4334
|
100
|
|
4334
|
0
|
7726
|
if($NOTES{$_[0]}){ return 1; } |
|
756
|
|
|
|
|
2460
|
|
256
|
3578
|
|
|
|
|
7814
|
else { return 0; } |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
sub unset { |
259
|
2979
|
|
|
2979
|
0
|
4198
|
foreach (@_){ |
260
|
3019
|
100
|
|
|
|
4990
|
if(! isset($_)){ return 0; } |
|
2683
|
|
|
|
|
7814
|
|
261
|
|
|
|
|
|
|
} |
262
|
296
|
|
|
|
|
502
|
foreach (@_){ |
263
|
317
|
|
|
|
|
813
|
$NOTES{$_} = 0; |
264
|
|
|
|
|
|
|
} |
265
|
296
|
|
|
|
|
1126
|
return 1; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
sub app { |
268
|
251
|
|
|
251
|
0
|
336
|
$NAME .= $_[0]; |
269
|
251
|
|
|
|
|
614
|
return 1; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
sub lower_octave_is { |
272
|
216
|
|
|
216
|
0
|
332
|
my %notes = map { ($_ => 1) } @_; # sets up %notes = ($_[0]=>1,$_[1]=>1 ...) |
|
792
|
|
|
|
|
1747
|
|
273
|
216
|
|
|
|
|
472
|
foreach my $i(0..11){ |
274
|
426
|
100
|
100
|
|
|
2779
|
if(($notes{$i} && ! $NOTES{$i}) || # if it's set in one but not the other |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
275
|
|
|
|
|
|
|
($NOTES{$i} && ! $notes{$i})){ # or the other way around |
276
|
214
|
|
|
|
|
1006
|
return 0; # then the test returns false |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} |
279
|
2
|
|
|
|
|
12
|
return 1; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub jws { |
283
|
0
|
|
|
0
|
|
|
return join(' ',@_); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
sub jwn { |
286
|
0
|
|
|
0
|
|
|
return join("\n",@_); |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
1; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head1 NAME |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Music::Chord::Namer - You give it notes, it names the chord. |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 SYNOPSIS |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
use Music::ChordName qw/chordname/; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
print chordname(qw/C E G/); # prints C |
304
|
|
|
|
|
|
|
print chordname(q/C E G/); # same (yes, array or string!) |
305
|
|
|
|
|
|
|
print chordname(qw/C Eb G Bb D/); # prints Cm9 |
306
|
|
|
|
|
|
|
print chordname(qw/G C Eb Bb D/); # prints Cm9/G |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 DESCRIPTION |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Music::ChordName optionally exports one sub, chordname, which accepts some notes as either a string |
311
|
|
|
|
|
|
|
or a list and returns the best chord name it can think of. |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head2 EXPORT |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
None by default. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=over 4 |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=item $bestnamescalar|@namesarray = chordname($notesstring|@notesarray) |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
chordname() accepts either a string of notes such as "C Eb G A#" or a list of notes such as |
322
|
|
|
|
|
|
|
qw/Ab Bb F Bb D/. In a scalar context it returns the best name it could think of to describe the |
323
|
|
|
|
|
|
|
chord made from the notes you gave it. In an array context it returns all of the names it thought |
324
|
|
|
|
|
|
|
of, sorted from best to worst (shortest to longest!) |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=head1 EXAMPLES |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# to print a bunch of guitar chord names with at lest 4 notes each, |
330
|
|
|
|
|
|
|
# all below 5th fret... |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
foreach my $s1(qw/- E F Gb G Ab/){ |
333
|
|
|
|
|
|
|
foreach my $s2(qw/- A Bb B C Db/){ |
334
|
|
|
|
|
|
|
foreach my $s3(qw/- D Eb E F Gb/){ |
335
|
|
|
|
|
|
|
foreach my $s4(qw/- G Ab A Bb/){ |
336
|
|
|
|
|
|
|
foreach my $s5(qw/- B C Db D Eb/){ |
337
|
|
|
|
|
|
|
foreach my $s6(qw/- E F Gb G Ab/){ |
338
|
|
|
|
|
|
|
my @notes = (); |
339
|
|
|
|
|
|
|
push @notes, $s1 unless $s1 eq '-'; |
340
|
|
|
|
|
|
|
push @notes, $s2 unless $s2 eq '-'; |
341
|
|
|
|
|
|
|
push @notes, $s3 unless $s3 eq '-'; |
342
|
|
|
|
|
|
|
push @notes, $s4 unless $s4 eq '-'; |
343
|
|
|
|
|
|
|
push @notes, $s5 unless $s5 eq '-'; |
344
|
|
|
|
|
|
|
push @notes, $s6 unless $s6 eq '-'; |
345
|
|
|
|
|
|
|
if(@notes >= 4){ |
346
|
|
|
|
|
|
|
print scalar(chordname(@notes)),' = ',join(' ',@notes),"\n"; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=head1 SEE ALSO |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
L could be combined nicely with this module. |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=head1 AUTHOR |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Jimi-Carlo Bukowski-Wills, jimi@webu.co.uk |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
Copyright (C) 2006 by Jimi-Carlo Bukowski-Wills |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
369
|
|
|
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.8.7 or, |
370
|
|
|
|
|
|
|
at your option, any later version of Perl 5 you may have available. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=cut |