#!/usr/bin/perl use strict; use Benchmark; my @modes = qw(Ionian Dorian Phrygian Lydian Mixolydian Aeolian Locria +n); my @notes = qw(C D E F G A B); my @prefs = qw(# b # b # b b # b # b #); my @accidentals = ("#", "b", " "); my @scales; $scales[0] = [qw(0 2 4 5 7 9 11)]; $scales[1] = [qw(1 3 5 6 8 10 0)]; $scales[2] = [qw(2 4 6 7 9 11 1)]; $scales[3] = [qw(3 5 7 8 10 0 2)]; $scales[4] = [qw(4 6 8 9 11 1 3)]; $scales[5] = [qw(5 7 9 10 0 2 4)]; $scales[6] = [qw(6 8 10 11 1 3 5)]; $scales[7] = [qw(7 9 11 0 2 4 6)]; $scales[8] = [qw(8 10 0 1 3 5 7)]; $scales[9] = [qw(9 11 1 2 4 6 8)]; $scales[10] = [qw(10 0 2 3 5 7 9)]; $scales[11] = [qw(11 1 3 4 6 8 10)]; #how many notes ahead are each mode my %modevalues = qw(Ionian 0 Dorian 2 Phrygian 4 Lydian 5 Mixolydian 7 + Aeolian 9 Locrian 11); #get random scale (note and mode) my $mode = int(rand($#modes+1)); my $accidental = int(rand($#accidentals+1)); my $note = int(rand($#notes+1)); #find out correct number scale from random scale my $numb = let2numb($notes[$note] . $accidentals[$accidental]); #conve +rt music note to corresponding number my $scale = $numb - $modevalues{$modes[$mode]}; #find +out which original scale the mode came from $scale += 12 if ($scale < 0); #corre +ct negative offset my @reference = @{$scales[$scale]}; #get t +he correct original scale my @take = splice(@reference,0,$mode); #conve +rt the original scale to the right mode @reference = (@reference, @take); #put t +he correct scale all together #print out what scale we want print $notes[$note], $accidentals[$accidental], " ", $modes[$mode], ": +\n"; #get response, convert to number music scale, and time it my $t0 = new Benchmark; my $cool = <STDIN>; my $t1 = new Benchmark; my ($measure) = timestr(timediff($t1, $t0)) =~ /^\s?(\d+ wallclock sec +s).*/; my @response = split(/\s/, $cool); foreach (@response) { $_ = let2numb($_); } #get correct scale in letter form my $correct; foreach (@reference) { $correct .= numb2let($_,$prefs[$scale])." "; } #check if correct then exit if (join(' ', @reference) eq join(' ', @response)) { print "You're Right! $measure\n"; } else { print "Sorry $measure\nThe correct scale was: $correct\n"; } exit; #function to convert a regular form music note into an number sub let2numb() { my ($let, $acc) = split(//, lc(shift @_)); my %cnotes = ("c", "0", "d", "2", "e", "4", "f", "5", "g", "7", "a +", "9", "b", "11"); my $change; if ($acc eq "b") { $change = -1; } elsif ($acc eq "#") { $change = 1; } else { $change = 0; } my $return = $cnotes{$let} + $change; if ($return > 11) { $return -= 12; } elsif ($return < 0) { $return += 12; } return $return; } #function to convert number form of a music scale note into basic lett +er scale, takes sharp or flat preference. sub numb2let() { my $number = shift; my $pref = shift; my @cnotes = qw(C h D h E F h G h A h B); if ($cnotes[$number] eq "h") { return ($pref eq "#") ? $cnotes[$number-1].$pref : $cnotes[$nu +mber+1].$pref; } else { return $cnotes[$number]; } }
In reply to Practice your major scale modes by chrono86
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |