Public/Invoke-Ditty.ps1
# TODO: documentation function Invoke-Ditty { [CmdletBinding(DefaultParameterSetName='Duration')] PARAM ( [Parameter(Mandatory,ValueFromRemainingArguments,ValueFromPipeline,Position=0)] [AllowEmptyCollection()] [string[]]$Notes, [Parameter(ParameterSetName='Duration')][int]$BaseDuration = 225, [Parameter(ParameterSetName='BPM',Mandatory)][int]$BPM, [Parameter(ParameterSetName='BPM')][ValidateSet(32,16,8,4)]$BaseNote = 'quarter' ) begin { $NoteNames = @{ 'B8' = 7902 'A#8' = 7459 'A8' = 7040 'G#8' = 6645 'G8' = 6272 'F#8' = 5920 'F8' = 5588 'E8' = 5274 'D#8' = 4978 'D8' = 4699 'C#8' = 4435 'C8' = 4186 'B7' = 3951 'A#7' = 3729 'A7' = 3520 'G#7' = 3322 'G7' = 3136 'F#7' = 2960 'F7' = 2794 'E7' = 2637 'D#7' = 2489 'D7' = 2349 'C#7' = 2217 'C7' = 2093 'B6' = 1976 'A#6' = 1865 'A6' = 1760 'G#6' = 1661 'G6' = 1568 'F#6' = 1480 'F6' = 1397 'E6' = 1319 'D#6' = 1245 'D6' = 1175 'C#6' = 1109 'C6' = 1047 'B5' = 988 'A#5' = 932 'A5' = 880 'G#5' = 831 'G5' = 784 'F#5' = 740 'F5' = 698 'E5' = 659 'D#5' = 622 'D5' = 587 'C#5' = 554 'C5' = 523 'B4' = 494 'A#4' = 466 'A4' = 440 'G#4' = 415 'G4' = 392 'F#4' = 370 'F4' = 349 'E4' = 330 'D#4' = 311 'D4' = 294 'C#4' = 277 'C4' = 262 'B' = 494 'A#' = 466 'A' = 440 'G#' = 415 'G' = 392 'F#' = 370 'F' = 349 'E' = 330 'D#' = 311 'D' = 294 'C#' = 277 'C' = 262 'B3' = 247 'A#3' = 233 'A3' = 220 'G#3' = 208 'G3' = 196 'F#3' = 185 'F3' = 175 'E3' = 165 'D#3' = 156 'D3' = 147 'C#3' = 139 'C3' = 131 'B2' = 123 'A#2' = 117 'A2' = 110 'G#2' = 104 'G2' = 98 'F#2' = 92 'F2' = 87 'E2' = 82 'D#2' = 78 'D2' = 73 'C#2' = 69 'C2' = 65 'B1' = 62 'A#1' = 58 'A1' = 55 'G#1' = 52 'G1' = 49 'F#1' = 46 'F1' = 44 'E1' = 41 'D#1' = 39 'D1' = 37 'C#1' = 35 'C1' = 33 'B0' = 31 'A#0' = 29 'A0' = 28 'p' = -1 } if($BPM){ $Multiplier = switch ($BaseNote) { 32 { 8 } 16 { 4 } 8 { 2 } default { 1 } } $BaseDuration = [timespan]::TicksPerMinute/[timespan]::TicksPerMillisecond/$BPM/$Multiplier } } process { foreach($Stanza in $Notes){ foreach($Note in $Stanza -split '[\s|,]+' | Where-Object { $_ }){ $Duration = $BaseDuration if($Note -match '(-+)(\d+)?$'){ $Note = $Note -replace '-.*$' if($Matches.ContainsKey(2)){ $Duration = $Matches[1].Length * [int]$Matches[2] } else { $Duration *= $Matches[1].Length } } if($NoteNames.ContainsKey($Note)){ $Note = $NoteNames[$Note] } else { $Note = [int]$Note } if($Note -lt 0){ Start-Sleep -Milliseconds $Duration } else { [Console]::Beep($Note, $Duration) } } } } } |