129 lines
3.5 KiB
PowerShell
129 lines
3.5 KiB
PowerShell
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)
|
|
}
|
|
}
|
|
}
|