ps/Modules/Cole.PowerShell.Developer/Public/Invoke-Notes.ps1

129 lines
3.5 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
Function Invoke-Notes {
<#
.SYNOPSIS
Play some musical notes using the console beep
.PARAMETER Notes
The notes values to be played. Consists of three parts: Pitch, Octave (optional), NoteType (optional)
Defaults to the octave "Treble C". Supports octaves from Subcontra to Five-lined (triple-high-C)
Defaults to quarternotes when none are provided.
.PARAMETER Tempo
Speed-change for duration of notes
.PARAMETER Output
Debug for showing what is being calculated
.NOTES
Found this on Reddit, copied it down for George. Enjoy George.
.LINK
https://www.reddit.com/r/PowerShell/comments/q8l24k/some_powershell_beep/
.LINK
https://www.reddit.com/r/PowerShell/comments/8wj4cu/i_wrote_a_powershell_script_that_uses_the_console/
.LINK
https://en.wikipedia.org/wiki/C_(musical_note)
.EXAMPLE
# Play a G eigth note in the 6th octave
# Play a F# eigth note in the 6th octave
# Play a G eigth note in the 6th octave
Invoke-Notes -Notes "G6E,F#6E,G6E" -Output
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$Notes,
[Parameter(Mandatory = $false)]
[int]$Tempo,
[Parameter(Mandatory = $false)]
[switch]$Output = $false
)
$tempoModifier = 1
$defaultNoteType = 'Q'
$defaultOctave = 5
if ($Tempo -gt 0) {
$tempoModifier = 100.0/$Tempo
} elseif ($Tempo -lt 0) {
Write-Warning "Tempo value supplied [$Tempo] is invalid (less than zero). It is ignored."
}
# W = Whole, H = Half, Q = Quarter, E = Eighth, S = Sixteenth
$NoteTypes = [PSCustomObject]@{
'W' = 1600
'W.' = 2000
'H' = 800
'H.' = 1000
'Q' = 400
'Q.' = 600
'E' = 200
'E.' = 300
'S' = 100
'S.' = 150
}
# Define the Subcontra octave frequencies
# We will calculate more octaves based from these
$NoteIndex = [PSCustomObject]@{
'C' = @(16.3516)
'C#' = @(17.32391)
'D' = @(18.35405)
'Eb' = @(19.44544)
'E' = @(20.60172)
'F' = @(21.82676)
'F#' = @(23.12465)
'G' = @(24.49971)
'G#' = @(25.95654)
'A' = @(27.50000)
'Bb' = @(29.13524)
'B' = @(30.86771)
<#Rest#>'R' = 0
}
foreach($note in $NoteIndex.PSObject.Properties.Name) {
$seed = $NoteIndex.$note[0]
$newValues = @([Math]::Round($seed,2))
# calculate 8 more octaves above the seed data
foreach($mult in 0..7) {
# this is the operation for 2^x -> (2 -shl $mult)
$newValues += [Math]::Round( ($seed * (2 -shl $mult)) ,2)
}
$noteIndex.$note = $newValues
}
$splitNotes = ($Notes -split ',')
foreach ($Note in $splitNotes) {
$Note -match '(?<Pitch>[A-G][#|b]?|[R])(?<Octave>[0-8])?(?<NoteType>[Ww|Hh|Qq|Ee|Ss][\.]?)?' | Out-Null
$Pitch = $matches['Pitch']
$noteType = $matches['NoteType']
$octave = $matches['Octave']
if ($null -eq $noteType) {
$noteType = $defaultNoteType
}
if ($null -eq $octave) {
$octave = $defaultOctave
}
[int]$Duration = $tempoModifier * ($NoteTypes.$noteType)
[int]$Frequency = $NoteIndex.$Pitch[$octave]
if ($Output) {
Write-Host "$Pitch $octave $noteType - $Duration - $Frequency"
}
if ($Pitch -eq 'R') {
Start-Sleep -Milliseconds $Duration
} else {
[Console]::beep($Frequency,$Duration)
}
}
}