Monday, June 25, 2012

PowerShell and Bass Guitar

I recently decided to try my hand at a musical instrument.  The bass guitar seemed like a good fit for me so I picked it up started a with a few lessons.  I quickly realized that in order to have any success with it, I needed to memorize the fret-board.  Given my affinity for PowerShell, I decided to blend the two.  Following is a script that I threw in my profile to prompt me upon start-up for a few notes.

function Get-BassNote {            
 param($Count=2)            
             
 $BassNotes = @{             
      "Fret0" = @{             
        "String1" = {E}            
        "String2" = {A}            
        "String3" = {D}            
        "String4" = {G} }            
      "Fret1" = @{            
        "String1" = {F}            
        "String2" = {A#}            
        "String3" = {D#}            
        "String4" = {G#} }            
      "Fret2" = @{            
        "String1" = {F#}            
        "String2" = {B}            
        "String3" = {E}            
        "String4" = {A} }            
      "Fret3" = @{            
        "String1" = {G}            
        "String2" = {C}            
        "String3" = {F}            
        "String4" = {A#} }            
      "Fret4" = @{            
        "String1" = {G#}            
        "String2" = {C#}            
        "String3" = {F#}            
        "String4" = {B} }            
      "Fret5" = @{            
        "String1" = {A}            
        "String2" = {D}            
        "String3" = {G}            
        "String4" = {C} }            
      "Fret6" = @{            
        "String1" = {A#}            
        "String2" = {D#}            
        "String3" = {G#}            
        "String4" = {C#} }            
      "Fret7" = @{            
        "String1" = {B}            
        "String2" = {E}            
        "String3" = {A}            
        "String4" = {D} }            
      "Fret8" = @{            
        "String1" = {C}            
        "String2" = {F}            
        "String3" = {A#}            
        "String4" = {D#} }             
      "Fret9" = @{            
        "String1" = {C#}            
        "String2" = {F#}            
        "String3" = {B}            
        "String4" = {E} }             
      "Fret10" = @{            
        "String1" = {D}            
        "String2" = {G}            
        "String3" = {C}            
        "String4" = {F} }            
      "Fret11" = @{            
        "String1" = {D#}            
        "String2" = {G#}            
        "String3" = {C#}            
        "String4" = {F#} }            
      "Fret12" = @{            
        "String1" = {E}            
        "String2" = {A}            
        "String3" = {D}            
        "String4" = {G} }            
    }            
             
    for ($i=1; $i-le$Count; $i++){            
        $fretNumber   = Get-Random -Minimum 0 -Maximum 12            
     $stringNumber = Get-Random -Minimum 1 -Maximum 4            
     [string]$Answer = $BassNotes."Fret$($FretNumber)"."String$($StringNumber)"            
     $prompt = "What is the note for string $($stringNumber), fret $($fretNumber)"            
     do { $Response = Read-Host $Prompt }             
        until ($Answer -eq $Response)            
 }            
}


Rock on!

6 comments:

Will said...

Looks good. Now, an interval generator would be a fun next project. : )

Shay Levy said...

Awesome!

Fret6 has the wrong notes, probably a copy/paste issue. It should read:
A#,D#,G#,C#

Joe Pruitt said...

Great inspiration. Here's one I whipped up for a Guitar with a visual fretboard presentation. Just adjust the $tuning variable to the number of frets and the root notes in your tuning and it will work for a bass as well. Hopefully this code comes across in the comment

$notes = @("A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#");
$num_notes = $notes.length;

$tuning = @("E", "A", "D", "G", "B", "E");
$num_strings = $tuning.length;

$num_frets = 21;

# Get Random string and fret
$string = Get-Random -Minimum 0 -Maximum $($num_strings - 1);
$fret = Get-Random -Minimum 0 -Maximum $num_frets

# Root index in notes array
$string_index = $( for($i=0; $i-lt$num_notes; $i++) { if($notes[$i] -eq $tuning[$string]) { $i; break;} } )

$note = $notes[($string_index + $fret) % $notes.length];

function Write-Fretboard()
{
param($string, $fret, $note);

# Tens Header
$line = " ";
# Write the fret rows
for($i=0; $i -le $num_frets; $i++) {
[int]$tens = $($i - ($i % 10)) / 10;
if ( $tens -eq 0 ) { [string]$tens = " "; }
$line += "$tens ";
}
Write-Host $line;

# Ones header
$line = " ";
for($i=0; $i -le $num_frets; $i++) {
[int]$ones = $i % 10;
$line += "$ones ";
}
Write-Host $line;

for($i=$num_strings-1; $i -ge 0; $i--) {
$line = "";
$root = $tuning[$i];
$line += "$root";
$line += ": ";
for($j=0; $j -le $num_frets; $j++) {
if ( ($i -eq $string) -and ($j -eq $fret ) ) {
$line += "X|";
} else {
$line += " |";
}
}
Write-Host $line;
}
}

Write-Fretboard -string $string -fret $fret -note $note;
Write-Host "String: $($string+1), Fret: $fret, String Index: $string_index, Note: $note";

Joe Pruitt said...

BTW, the output looks something like this:

PS D:\dev\powershell\Utilities> .\Guitar-Notes.ps1
1 1 1 1 1 1 1 1 1 1 2 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
E: | | | | | | | | | | | | | | | | | | | | | |
B: | | | | | | | | | | | | | | | | | | | | | |
G: | | | | | | | | | | | | | |X| | | | | | | |
D: | | | | | | | | | | | | | | | | | | | | | |
A: | | | | | | | | | | | | | | | | | | | | | |
E: | | | | | | | | | | | | | | | | | | | | | |
String: 4, Fret: 14, String Index: 10, Note Index: 10, Note: A

Wes Stahler said...

Shay - thanks for catching the cut and paste error - fixed.

Wes Stahler said...

Joe - Excellent! Like the visual perspective.