line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Music::Scales; |
2
|
5
|
|
|
5
|
|
164909
|
use strict; |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
247
|
|
3
|
5
|
|
|
5
|
|
6609
|
use Text::Abbrev; |
|
5
|
|
|
|
|
335
|
|
|
5
|
|
|
|
|
539
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
BEGIN { |
6
|
5
|
|
|
5
|
|
32
|
use Exporter (); |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
108
|
|
7
|
5
|
|
|
5
|
|
106
|
use vars qw ($VERSION @ISA @EXPORT); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
588
|
|
8
|
5
|
|
|
5
|
|
12
|
$VERSION = 0.07; |
9
|
5
|
|
|
|
|
73
|
@ISA = qw (Exporter); |
10
|
5
|
|
|
|
|
13618
|
@EXPORT = qw (get_scale_notes get_scale_nums get_scale_offsets is_scale get_scale_PDL get_scale_MIDI); |
11
|
|
|
|
|
|
|
} |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Scales - supply necessary notes / offsets for musical scales |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSIS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use Music::Scales; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my @maj = get_scale_notes('Eb'); # defaults to major |
23
|
|
|
|
|
|
|
print join(" ",@maj); # "Eb F G Ab Bb C D" |
24
|
|
|
|
|
|
|
my @blues = get_scale_nums('bl'); # 'bl','blu','blue','blues' |
25
|
|
|
|
|
|
|
print join(" ",@blues); # "0 3 5 6 7 10" |
26
|
|
|
|
|
|
|
my %min = get_scale_offsets ('G','mm',1); # descending melodic minor |
27
|
|
|
|
|
|
|
print map {"$_=$min{$_} "} sort keys %min; # "A=0 B=-1 C=0 D=0 E=-1 F=0 G=0" |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 DESCRIPTION |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Given a keynote A-G(#/b) and a scale-name, will return the scale, |
33
|
|
|
|
|
|
|
either as an array of notenames or as a hash of semitone-offsets for each note. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 METHODS |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head2 get_scale_nums($scale[,$descending]) |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
returns an array of semitone offsets for the requested scale, ascending/descending the given scale for one octave. |
40
|
|
|
|
|
|
|
The descending flag determines the direction of the scale, and also affects those scales (such as melodic minor) where the notes vary depending upon the direction. |
41
|
|
|
|
|
|
|
Scaletypes and valid values for $scale are listed below. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head2 get_scale_notes($notename[,$scale,$descending,$keypref]) |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
returns an array of notenames, starting from the given keynote. |
46
|
|
|
|
|
|
|
Enharmonic equivalencies (whether to use F# or Gb, for instance) are calculated based on the keynote and the scale. Basically, it attempts to do the Right Thing if the scale is an 8-note one, |
47
|
|
|
|
|
|
|
(the 7th in G harmonic minor being F# rather than Gb, although G minor is a 'flat' key), but for any other scales, (Chromatic, blues etc.) it picks equivalencies based upon the keynote. |
48
|
|
|
|
|
|
|
This can be overidden with $keypref, setting to be either '#' or 'b' for sharps and flats respectively. Cruftiness abounds here :) |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head2 get_scale_offsets($notename[,$scale,$descending,$keypref]) |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
as get_scale_notes(), except it returns a hash of notenames with the values being a semitone offset (-1, 0 or 1) as shown in the synopsis. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 get_scale_MIDI($notename,$octave[,$scale,$descending]) |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
as get_scale_notes(), but returns an array of MIDI note-numbers, given an octave number (-1..9). |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 get_scale_PDL($notename,$octave[,$scale,$descending]) |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
as get_scale_MIDI(), but returns an array of PDL-format notes. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 is_scale($scalename) |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
returns true if $scalename is a valid scale name used in this module. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head1 SCALES |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Scales can be passed either by name or number. |
69
|
|
|
|
|
|
|
The default scale is 'major' if none / invalid is given. |
70
|
|
|
|
|
|
|
Text::Abbrev is used on scalenames, so they can be as abbreviated as unambiguously possible ('dor','io' etc.). |
71
|
|
|
|
|
|
|
Other abbreviations are shown in brackets. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
1 ionian / major / hypolydian |
74
|
|
|
|
|
|
|
2 dorian / hypmixolydian |
75
|
|
|
|
|
|
|
3 phrygian / hypoaeolian |
76
|
|
|
|
|
|
|
4 lydian / hypolocrian |
77
|
|
|
|
|
|
|
5 mixolydian / hypoionian |
78
|
|
|
|
|
|
|
6 aeolian / hypodorian / minor / m |
79
|
|
|
|
|
|
|
7 locrian / hypophrygian |
80
|
|
|
|
|
|
|
8 harmonic minor / hm |
81
|
|
|
|
|
|
|
9 melodic minor / mm |
82
|
|
|
|
|
|
|
10 blues |
83
|
|
|
|
|
|
|
11 pentatonic (pmajor) |
84
|
|
|
|
|
|
|
12 chromatic |
85
|
|
|
|
|
|
|
13 diminished |
86
|
|
|
|
|
|
|
14 wholetone |
87
|
|
|
|
|
|
|
15 augmented |
88
|
|
|
|
|
|
|
16 hungarian minor |
89
|
|
|
|
|
|
|
17 3 semitone |
90
|
|
|
|
|
|
|
18 4 semitone |
91
|
|
|
|
|
|
|
19 neapolitan minor (nmin) |
92
|
|
|
|
|
|
|
20 neapolitan major (nmaj) |
93
|
|
|
|
|
|
|
21 todi |
94
|
|
|
|
|
|
|
22 marva |
95
|
|
|
|
|
|
|
23 persian |
96
|
|
|
|
|
|
|
24 oriental |
97
|
|
|
|
|
|
|
25 romanian |
98
|
|
|
|
|
|
|
26 pelog |
99
|
|
|
|
|
|
|
27 iwato |
100
|
|
|
|
|
|
|
28 hirajoshi |
101
|
|
|
|
|
|
|
29 egyptian |
102
|
|
|
|
|
|
|
30 pentatonic minor (pminor) |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 EXAMPLE |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
This will print every scale in every key, adjusting the enharmonic equivalents accordingly. |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
foreach my $note qw (C C# D D# E F F# G G# A A# B) { |
109
|
|
|
|
|
|
|
foreach my $mode (1..30) { |
110
|
|
|
|
|
|
|
my @notes = get_scale_notes($note,$mode); |
111
|
|
|
|
|
|
|
push @notes, get_scale_notes($note,$mode,1); # descending |
112
|
|
|
|
|
|
|
print join(" ",@notes),"\n"; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 TODO |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Add further range of scales from http://www.cs.ruu.nl/pub/MIDI/DOC/scales.zip |
120
|
|
|
|
|
|
|
Improve enharmonic eqivalents. |
121
|
|
|
|
|
|
|
Microtones |
122
|
|
|
|
|
|
|
Generate ragas,gamelan etc. - maybe needs an 'ethnic' subset of modules |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head1 AUTHOR |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Ben Daglish (bdaglish@surfnet-ds.co.uk) |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Thanks to Steve Hay for pointing out my 'minor' mix-up and many suggestions. |
129
|
|
|
|
|
|
|
Thanks also to Gene Boggs for the 'is_scale' suggestion / code. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head1 BUGS |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
A few enharmonic problems still... |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
All feedback most welcome. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head1 COPYRIGHT |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Copyright (c) 2003, Ben Daglish. All Rights Reserved. |
140
|
|
|
|
|
|
|
This program is free software; you can redistribute |
141
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
The full text of the license can be found in the |
144
|
|
|
|
|
|
|
LICENSE file included with this module. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head1 SEE ALSO |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
PDL::Audio::Scale, perl(1). |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my %modes = qw(ionian 1 major 1 hypolydian 1 dorian 2 hypomyxolydian 2 |
154
|
|
|
|
|
|
|
phrygian 3 hypoaeolian 3 lydian 4 hypolocrian 4 mixolydian 5 hypoionian 5 |
155
|
|
|
|
|
|
|
aeolian 6 minor 6 m 6 hypodorian 6 locrian 7 hypophrygian 7 |
156
|
|
|
|
|
|
|
harmonicminor 8 hm 8 melodicminor 9 mm 9 |
157
|
|
|
|
|
|
|
blues 10 pentatonic 11 pmaj 11 chromatic 12 diminished 13 wholetone 14 |
158
|
|
|
|
|
|
|
augmented 15 hungarianminor 16 3semitone 17 4semitone 18 |
159
|
|
|
|
|
|
|
neapolitanminor 19 nmin 19 neapolitanmajor 20 nmaj 20 |
160
|
|
|
|
|
|
|
todi 21 marva 22 persian 23 oriental 24 romanian 25 pelog 26 |
161
|
|
|
|
|
|
|
iwato 27 hirajoshi 28 egyptian 29 pminor 30 pentatonicminor 30 |
162
|
|
|
|
|
|
|
); |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
my %abbrevs = abbrev(keys %modes); |
165
|
|
|
|
|
|
|
while (my ($k,$v) = each %abbrevs) { |
166
|
|
|
|
|
|
|
$modes{$k} = $modes{$v}; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my @scales=([0,2,4,5,7,9,11], # Ionian(1) |
170
|
|
|
|
|
|
|
[0,2,3,5,7,9,10], # Dorian (2) |
171
|
|
|
|
|
|
|
[0,1,3,5,7,8,10], # Phrygian (3) |
172
|
|
|
|
|
|
|
[0,2,4,6,7,9,11], # Lydian (4) |
173
|
|
|
|
|
|
|
[0,2,4,5,7,9,10], # Mixolydian (5) |
174
|
|
|
|
|
|
|
[0,2,3,5,7,8,10], # Aeolian (6) |
175
|
|
|
|
|
|
|
[0,1,3,5,6,8,10], # Locrian (7) |
176
|
|
|
|
|
|
|
[0,2,3,5,7,8,11], # Harmonic Minor (8) |
177
|
|
|
|
|
|
|
[0,2,3,5,7,9,11], # Melodic Minor (9) |
178
|
|
|
|
|
|
|
[0,3,5,6,7,10], # Blues (10) |
179
|
|
|
|
|
|
|
[0,2,4,7,9], # Pentatonic (11) |
180
|
|
|
|
|
|
|
[0,1,2,3,4,5,6,7,8,9,10,11],# Chromatic (12) |
181
|
|
|
|
|
|
|
[0,2,3,5,6,8,9,11], # Diminished (13) |
182
|
|
|
|
|
|
|
[0,2,4,6,8,10], # Whole tone(14) |
183
|
|
|
|
|
|
|
[0,3,4,7,8,11], # Augmented (15) |
184
|
|
|
|
|
|
|
[0,2,3,6,7,8,11], # Hungarian minor (16) |
185
|
|
|
|
|
|
|
[0,3,6,9], # 3 semitone (dimished arpeggio) (17) |
186
|
|
|
|
|
|
|
[0,4,8], # 4 semitone (augmented arpeggio) (18) |
187
|
|
|
|
|
|
|
[0,1,3,5,7,8,11], # Neapolitan minor (19) |
188
|
|
|
|
|
|
|
[0,1,3,5,7,9,11], # Neapolitan major (20) |
189
|
|
|
|
|
|
|
[0,1,3,6,7,8,11], # Todi (Indian) (21) |
190
|
|
|
|
|
|
|
[0,1,4,6,7,9,11], # Marva (Indian) (22) |
191
|
|
|
|
|
|
|
[0,1,4,5,6,8,11], # Persian (23) |
192
|
|
|
|
|
|
|
[0,1,4,5,6,9,10], # Oriental (24) |
193
|
|
|
|
|
|
|
[0,2,3,6,7,9,10], # Romanian (25) |
194
|
|
|
|
|
|
|
[0,1,3,7,10], # Pelog (Balinese) (26) |
195
|
|
|
|
|
|
|
[0,1,5,6,10], # Iwato (Japanese) (27) |
196
|
|
|
|
|
|
|
[0,2,3,7,8], # Hirajoshi (Japanese) (28) |
197
|
|
|
|
|
|
|
[0,2,5,7,10], # Egyptian (29) |
198
|
|
|
|
|
|
|
[0,3,5,7,10], # Pentatonic Minor (30) |
199
|
|
|
|
|
|
|
); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub get_scale_nums { |
202
|
14
|
|
|
14
|
1
|
19
|
my ($mode,$descending) = @_; |
203
|
14
|
|
|
|
|
33
|
$mode = get_mode($mode); |
204
|
14
|
|
|
|
|
19
|
my @dists = @{$scales[$mode-1]}; |
|
14
|
|
|
|
|
54
|
|
205
|
14
|
50
|
66
|
|
|
50
|
if ($descending && $mode == 9) { |
206
|
0
|
|
|
|
|
0
|
$dists[5]-- ;$dists[6]--; |
|
0
|
|
|
|
|
0
|
|
207
|
|
|
|
|
|
|
} |
208
|
14
|
100
|
|
|
|
68
|
($descending) ? reverse @dists : @dists; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub get_scale_offsets { |
212
|
0
|
|
|
0
|
1
|
0
|
my @scale = get_scale_notes(@_); |
213
|
0
|
|
|
|
|
0
|
my %key_alts = qw(C 0 D 0 E 0 F 0 G 0 A 0 B 0); |
214
|
0
|
|
|
|
|
0
|
foreach (@scale) { |
215
|
0
|
0
|
|
|
|
0
|
$key_alts{$_}++ if s/#//; |
216
|
0
|
0
|
|
|
|
0
|
$key_alts{$_}-- if s/b//; |
217
|
|
|
|
|
|
|
} |
218
|
0
|
|
|
|
|
0
|
%key_alts; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub get_mode { |
222
|
23
|
|
100
|
23
|
0
|
56
|
my $mode = shift() || 1; |
223
|
23
|
|
|
|
|
167
|
$mode =~ s/[^a-zA-Z0-9]//g; |
224
|
23
|
100
|
|
|
|
95
|
$mode = $modes{lc($mode)} unless $mode =~/^[0-9]+$/; |
225
|
23
|
50
|
33
|
|
|
125
|
($mode && ($mode <= @scales)) ? $mode : 1; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub note_to_num { |
229
|
46
|
|
|
46
|
0
|
54
|
my $note = shift(); |
230
|
46
|
|
|
|
|
492
|
my %note2num = ('A','0','A#','1','BB','1','B','2','C','3','C#','4','DB','4','D','5','D#','6','EB','6','E','7','F','8','F#','9','GB','9','G','10','G#','11','AB','11'); |
231
|
46
|
50
|
|
|
|
117
|
return $note if ($note =~/^[0-9]+$/); |
232
|
46
|
50
|
|
|
|
268
|
(defined $note2num{uc($note)}) ? $note2num{uc($note)} : 0; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub note_to_MIDI { |
236
|
3
|
|
|
3
|
0
|
4
|
my ($note,$octave) = @_; |
237
|
3
|
|
|
|
|
9
|
((note_to_num($note)+9) % 12) + (12 * ++$octave ); |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub get_scale_MIDI { |
241
|
3
|
|
|
3
|
1
|
14
|
my ($note,$octave,$mode,$descending) = @_; |
242
|
3
|
|
|
|
|
8
|
my $basenum = note_to_MIDI($note,$octave); |
243
|
3
|
|
|
|
|
11
|
return map {$basenum + $_} get_scale_nums($mode,$descending); |
|
21
|
|
|
|
|
51
|
|
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub get_scale_PDL { |
247
|
4
|
|
|
4
|
1
|
16
|
my ($note,$octave,$mode,$descending,$keypref) = @_; |
248
|
4
|
|
|
|
|
11
|
scale_to_PDL($octave,get_scale_notes($note,$mode,$descending,$keypref)); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub get_scale_notes { |
252
|
9
|
|
|
9
|
1
|
26
|
my ($keynote,$mode,$descending,$keypref) = @_; |
253
|
9
|
|
|
|
|
35
|
my @notes = ('A'..'G'); |
254
|
9
|
|
|
|
|
20
|
my @nums = (2,1,2,2,1,2,2); |
255
|
|
|
|
|
|
|
|
256
|
9
|
|
|
|
|
23
|
$keynote =~ s/^[a-z]/\u$&/; |
257
|
9
|
50
|
|
|
|
27
|
$keypref='' unless defined $keypref; |
258
|
9
|
|
|
|
|
29
|
my $keynum = note_to_num(uc($keynote)); |
259
|
9
|
|
|
|
|
25
|
$mode = get_mode($mode); |
260
|
9
|
|
|
|
|
21
|
my @dists = get_scale_nums($mode,$descending); |
261
|
9
|
100
|
|
|
|
24
|
@dists = reverse @dists if $descending; |
262
|
9
|
|
|
|
|
15
|
my @scale = map {($_+$keynum-$dists[0])%12} @dists; |
|
67
|
|
|
|
|
121
|
|
263
|
9
|
100
|
66
|
|
|
57
|
$keypref='b' if (!$keypref && $descending && $mode == 12); #prefer flat descending chromatic |
|
|
|
100
|
|
|
|
|
264
|
|
|
|
|
|
|
|
265
|
9
|
|
|
|
|
97
|
my %num2note = (0,'A',1,'A#',2,'B',3,'C',4,'C#',5,'D',6,'D#',7,'E',8,'F',9,'F#',10,'G',11,'G#'); |
266
|
9
|
100
|
100
|
|
|
65
|
%num2note = (0,'A',1,'Bb',2,'B',3,'C',4,'Db',5,'D',6,'Eb',7,'E',8,'F',9,'Gb',10,'G',11,'Ab') if (($keypref eq 'b') || ($keynote =~ /.b/i)); |
267
|
9
|
|
|
|
|
16
|
my @mscale = $keynote; |
268
|
9
|
100
|
|
|
|
23
|
if (@scale > 7) { # we're not bothered by niceties, so just convert |
269
|
2
|
|
|
|
|
5
|
@mscale = map {$num2note{$_}} @scale; |
|
24
|
|
|
|
|
81
|
|
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
else { |
272
|
7
|
50
|
|
|
|
19
|
$keynote = $num2note{$keynote} if $keynote =~/^[0-9]+$/; |
273
|
7
|
|
|
|
|
9
|
my $kk = $keynote; $kk =~ s/b|\#//; $kk = ord($kk) - ord('A'); |
|
7
|
|
|
|
|
31
|
|
|
7
|
|
|
|
|
10
|
|
274
|
7
|
|
|
|
|
18
|
foreach(0..$kk-1) {# rotate to keynote |
275
|
27
|
|
|
|
|
60
|
push @notes,shift(@notes); |
276
|
27
|
|
|
|
|
41
|
push @nums,shift(@nums); |
277
|
|
|
|
|
|
|
} |
278
|
7
|
|
|
|
|
34
|
push @notes,shift(@notes); |
279
|
7
|
|
|
|
|
10
|
shift(@dists); |
280
|
7
|
|
|
|
|
11
|
my $cu = shift(@nums); |
281
|
7
|
100
|
|
|
|
20
|
$cu++ if ($keynote =~ /b/); |
282
|
7
|
100
|
|
|
|
19
|
$cu-- if ($keynote =~ /#/); |
283
|
7
|
|
|
|
|
12
|
foreach (@dists) { |
284
|
36
|
|
|
|
|
43
|
my $m = $_ - $cu; |
285
|
36
|
|
|
|
|
42
|
my $ns = shift(@nums); |
286
|
36
|
|
|
|
|
42
|
push @nums,$ns; |
287
|
36
|
|
|
|
|
47
|
my $n = shift(@notes); |
288
|
36
|
|
|
|
|
45
|
push @notes,$n; |
289
|
36
|
|
100
|
|
|
198
|
while (abs($m) > 2 || (@scale < 7 && abs($m) >= $ns)) { # step up/down notes, 'reducing' flats/sharps |
|
|
|
33
|
|
|
|
|
290
|
6
|
|
|
|
|
8
|
$n = shift(@notes); push @notes,$n; |
|
6
|
|
|
|
|
7
|
|
291
|
6
|
50
|
|
|
|
12
|
if ($m > 0) {$m -= $ns;$cu += $ns } |
|
6
|
0
|
|
|
|
5
|
|
|
6
|
|
|
|
|
8
|
|
|
0
|
|
|
|
|
0
|
|
292
|
0
|
|
|
|
|
0
|
elsif ($m < 0){$m += $ns;$cu -= $ns} |
293
|
6
|
|
|
|
|
6
|
$ns = shift(@nums); push @nums,$ns; |
|
6
|
|
|
|
|
31
|
|
294
|
|
|
|
|
|
|
} |
295
|
36
|
100
|
|
|
|
78
|
$n .= '#' x $m if ($m > 0); |
296
|
36
|
100
|
|
|
|
217
|
$n .= 'b' x abs($m) if ($m < 0); |
297
|
36
|
|
|
|
|
51
|
push @mscale,$n; |
298
|
36
|
|
|
|
|
62
|
$cu += $ns; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
} |
301
|
9
|
100
|
|
|
|
32
|
if ($descending) { |
302
|
2
|
|
|
|
|
3
|
@mscale = reverse @mscale; |
303
|
2
|
|
|
|
|
7
|
unshift @mscale,pop(@mscale); |
304
|
|
|
|
|
|
|
} |
305
|
9
|
|
|
|
|
101
|
@mscale; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub is_scale { |
310
|
6
|
|
|
6
|
1
|
18
|
my $name = shift(); |
311
|
6
|
|
|
|
|
14
|
$name =~ s/[^a-zA-Z0-9]//g; |
312
|
6
|
100
|
|
|
|
41
|
return exists $modes{lc $name} ? 1 : 0; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub scale_to_PDL { |
316
|
4
|
|
|
4
|
0
|
154
|
my ($octave,@scale)=@_; |
317
|
4
|
|
|
|
|
4
|
my @result; |
318
|
|
|
|
|
|
|
my $descending; |
319
|
4
|
|
|
|
|
9
|
my $n1 = note_to_num($scale[0]); |
320
|
4
|
|
|
|
|
7
|
my $n2 = note_to_num($scale[1]); |
321
|
4
|
100
|
100
|
|
|
21
|
if ($n2 < $n1 && ($n1-$n2 < 5)) { |
322
|
1
|
|
|
|
|
2
|
$descending = 1; |
323
|
1
|
|
|
|
|
2
|
@scale = reverse @scale; |
324
|
|
|
|
|
|
|
} |
325
|
4
|
|
|
|
|
8
|
my $last = (note_to_num($scale[0]) + 9) % 12; |
326
|
4
|
|
|
|
|
6
|
foreach (@scale) { |
327
|
22
|
|
|
|
|
40
|
my $n = (note_to_num($_) + 9) % 12; |
328
|
22
|
100
|
|
|
|
43
|
$octave++ if ($last > $n); #switched over octave at 'c' |
329
|
22
|
|
|
|
|
34
|
s/\#/s/g; |
330
|
22
|
|
|
|
|
28
|
s/b/f/g; |
331
|
22
|
|
|
|
|
38
|
push @result,lc($_).$octave; |
332
|
22
|
|
|
|
|
35
|
$last = $n; |
333
|
|
|
|
|
|
|
} |
334
|
4
|
100
|
|
|
|
10
|
@result = reverse @result if $descending; |
335
|
4
|
|
|
|
|
38
|
@result; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
1; |
339
|
|
|
|
|
|
|
__END__ |