Jump to content

Frohe Weihnachten :-)


Empfohlene Beiträge

Geschrieben (bearbeitet)

Update: Jetzt mit Kerzen in weiß und gelber Flamme :-) 

# Jingle Bells in PowerShell + ASCII-Weihnachtsbaum
  
Clear-Host

# Frequenzen (in Hz)
$notes = @{
     'C'    = 523
     'D'    = 587
     'E'    = 659
     'F'    = 698
     'G'    = 784
     'A'    = 880
     'H'    = 988
     'Rest' = 0
}

function Play-Note {
     param(
         [string]$note,
         [int]$duration
     )

     if ($note -eq 'Rest') {
         Start-Sleep -Milliseconds $duration
     } else {
         [console]::Beep($notes[$note], $duration)
     }
}

# Baum-Job starten, der die Zeilen zeitverzögert erzeugt
$treeJob = Start-Job -ScriptBlock {
   $treeLines = @(
     '',
     '           *',
     '        * *** *',
     '        |*****|',
     '      * ******* *',
     '      |*********|',
     '    * *********** *',
     '    |*************|',
     '    ***************',
     '   *****************',
     '          |||',
     '          |||',
     ''
     '   Frohe Weihnachten!'
   )

   $lineDelay = 600
   foreach ($line in $treeLines) {
     Write-Output $line
     Start-Sleep -Milliseconds $lineDelay
   }
}

# Vereinfachte "Jingle Bells"-Melodie
$melody = @(
     # "Jingle bells, jingle bells, jingle all the way"
     @('E',400), @('E',400), @('E',800),
     @('E',400), @('E',400), @('E',800),
     @('E',400), @('G',400), @('C',400), @('D',400),
     @('E',1000),

     # "Oh what fun it is to ride in a one-horse open sleigh"
     @('F',400), @('F',400), @('F',400), @('F',400),
     @('F',400), @('E',400), @('E',400), @('E',200),
     @('E',200), @('D',400), @('D',400), @('E',400),
     @('D',800), @('G',800)
)

# Zähler für bereits ausgegebene Baum-Zeilen
$printedCount = 0

# Hilfsfunktion für farbige Ausgabe
function Show-TreeLine {
     param([string]$text)
     if ($text -match '^( +)(\* |\|)(\*+)( \*|\|)$') {
       # Kerzen sind weiß, Flammen gelb, Nadeln grün
       if ($matches[2] -eq '|') {
         $Candle = [consolecolor]::White
       } else {
         $Candle = [consolecolor]::Yellow
       }
       Write-Host $matches[1] -NoNewline
       Write-Host $matches[2] -ForegroundColor $Candle -NoNewline
       Write-Host $matches[3] -ForegroundColor Green -NoNewline
       Write-Host $matches[4] -ForegroundColor $Candle
     } elseif ($text -match 'Weihnachten') {
         Write-Host $text -ForegroundColor Red
     } elseif ($text.Trim() -eq '|||') {
         Write-Host $text -ForegroundColor DarkYellow
     } else {
         Write-Host $text -ForegroundColor Green
     }
}

# Musik abspielen und Baum "wachsen" lassen
foreach ($noteEntry in $melody) {
     # Alle bisher vom Job erzeugten Zeilen holen, aber im Job behalten
     $allOutput = Receive-Job $treeJob -Keep

     if ($allOutput) {
         # Sicherheits-Cast zu Array (auch wenn nur eine Zeile da ist)
         $allLines = @($allOutput)

         if ($allLines.Count -gt $printedCount) {
             # Nur wirklich neue Zeilen ausgeben (Index-basiert)
             for ($i = $printedCount; $i -lt $allLines.Count; $i++) {
                 $text = [string]$allLines[$i]
                 Show-TreeLine $text
             }
             # Zähler aktualisieren
             $printedCount = $allLines.Count
         }
     }

     # Note spielen
     $note = $noteEntry[0]
     $dur  = $noteEntry[1]
     Play-Note -note $note -duration $dur
}

# Nach der Melodie sicherstellen, dass der Baum komplett ausgegeben ist
Wait-Job $treeJob | Out-Null
$allOutput = Receive-Job $treeJob

if ($allOutput) {
     $allLines = @($allOutput)

     if ($allLines.Count -gt $printedCount) {
         for ($i = $printedCount; $i -lt $allLines.Count; $i++) {
             $text = [string]$allLines[$i]
             Show-TreeLine $text
         }
     }
}

Remove-Job $treeJob | Out-Null

if ($host -match 'Console') {
   Write-Host ''
   Write-Host 'Fertig! Drücke eine Taste zum Beenden...' -ForegroundColor Yellow
   [void][System.Console]::ReadKey($true)
}

 

bearbeitet von daabm
  • Like 7
Geschrieben

Fingerübung: Implementiere eine Oktavsteuerung über eine entsprechende Variable $Oktave Lachend https://www.theorie-musik.de/grundlagen/tonhoehen-und-tonnamen-notennamen/ 

Verwende dabei 440 Hz als Bezugsgröße und berechne für die jeweilige Oktave alle relevanten Tonfrequenzen, statt diese als Konstante zu definieren - https://de.wikipedia.org/wiki/Frequenzen_der_gleichstufigen_Stimmung

Bonusaufgabe: Ermögliche eine beliebige Frequenz als "Basisfrequenz". Wahlweise durch Angabe des Basis-Tons ("C" etc.) oder durch Angabe einer Frequenz (523 etc.)

 

PS: In der Powershell Konsole spielt es schlecht, in der ISE läuft es seltsamerweise besser.

  • Danke 1
Geschrieben

Update 2: Die KI hat natürlich den Baum in einem Job gemalt und die Melodie im Vordergrund gespielt. Das klappt nicht wirklich gut, wenn man da dann noch die Ausgabe vom Baum abholen muss... Andersrum ist viel besser :-) Musik in einem Job spielen lassen und den Baum in Vordergrund malen. Dann noch Notenhöhen dynamisch berechnen und die Laufgeschwindigkeit variabel machen.

 

# Jingle Bells in PowerShell + ASCII-Weihnachtsbaum

Clear-Host

$baseFrequency, $baseDuration = 523, 100 # Basistonhöhe 523 = c1, Basisdauer 100ms
$scaling = [math]::Pow(2,1/12)  # ein Halbtonschritt
# Noten-Liste, damit die Melodie lesbar bleibt - könnte man auch über numerische Indizes machen,
# aber dann kann das niemand mehr lesen.
$notes = @('C','Cis','D','Dis','E','F','Fis','G','Gis','A','B','H')
$notemap = for ($i = 0; $i -lt $notes.Length; $i++) {
    # Frequenzen der Halbtöne berechnen
    @{$notes[$i] = $baseFrequency * [math]::Pow($scaling, $i)}
}

# Vereinfachte "Jingle Bells"-Melodie
$melody = @(
    # "Jingle bells, jingle bells, jingle all the way"
    @('E',4), @('E',4), @('E',8), @('E',4), @('E',4), @('E',8),
    @('E',4), @('G',4), @('C',4), @('D',4), @('E',10),

    # "Oh what fun it is to ride in a one-horse open sleigh"
    @('F',4), @('F',4), @('F',4), @('F',4), @('F',4), @('E',4), @('E',4),
    @('E',2), @('E',2), @('E',4), @('D',4), @('D',4), @('E',4), @('D',8), @('G',8)
)

# Melodiedauer berechnen, um den Baum in der richtigen Geschwindigkeit auszugeben
$melodyDuration = 0
$melody | ForEach-Object { $melodyDuration += $_[1] }

# Melodie-Job starten
$musicJob = Start-Job -ScriptBlock {
    param($melody, $notemap, $baseDuration)
    foreach ($note in $melody) {
        [console]::Beep($notemap.$($note[0]), $note[1] * $baseDuration)
    }
} -ArgumentList ($melody, $notemap, $baseDuration)

# Baum-Zeilen im Hauptskript
$treeLines = @(
    '',
    '           +',
    '           |',
    '           *',
    '        * *** *',
    '        | *** |',
    '      * ******* *',
    '      | ******* |',
    '    * *********** *',
    '    | *********** |',
    '    ***************',
    '   *****************',
    '          |||',
    '         /|||\',
    '',
    '   Frohe Weihnachten!',
    ''
)

# Baum im Hauptskript "wachsen" lassen, während die Musik im Job läuft
$lineDelay = $melodyDuration / $treeLines.Count
foreach ($line in $treeLines) {
    switch -Regex ($line) {
        '^ +[\+\|]$' {   # Baumspitze
            Write-Host $line -ForegroundColor Yellow
            break
        }
        '^( +)(\* |\| )(\*+)( \*| \|)$' {
            # Kerzen sind weiß, Flammen gelb, Nadeln dazwischen grün
            $Candle = [consolecolor]::Yellow
            if ($matches[2] -eq '| ' ) {    # Kerze
                $Candle = [consolecolor]::White
            }
            Write-Host $matches[1] -NoNewline
            Write-Host $matches[2] -ForegroundColor $Candle -NoNewline
            Write-Host $matches[3] -ForegroundColor Green -NoNewline
            Write-Host $matches[4] -ForegroundColor $Candle
            break
        }
        'Weihnachten' {
            Write-Host $line -ForegroundColor Red
            break
        }
        '\|{3}' {   # Baumstamm
            Write-Host $line -ForegroundColor DarkYellow
            break
        }
        default {   # Gewöhnliche Nadeln ohne Kerze
            Write-Host $line -ForegroundColor Green
        }
    }
    Start-Sleep -Milliseconds ($lineDelay * $baseDuration)
}

# Warten, bis die Melodie fertig ist
Wait-Job $musicJob | Out-Null
Remove-Job $musicJob | Out-Null

 

  • Danke 2
Geschrieben
Am 22.12.2025 um 19:18 schrieb NilsK:

also, zumindest in der Konsole von VS Code kommt die Melodie doch etwas unsortiert raus.

Tag 1, Minute ~35 meines PowerShell-Lehrgangs für Anfänger: "Denkt daran, jeden Code immer in der Umgebung zu testen, in der er später auch laufen soll." Das war zu PowerShell 3.0-Zeiten :-) 

  • Haha 2
Geschrieben

Fröhliche Weihnachten und allseits ruhige und entspannte Feiertage. 🎄

 

Wenn Ihr unterwegs seid, dann wünsche ich eine gute Reise und für alle, die Dienst haben, eine ausfallfreie Zeit. 

Wer Zeit hat, kann ja das PS Script ausprobieren - aber bitte am lokalen Client ;)

Bis die Tage :spock:

  • Like 3

Erstelle ein Benutzerkonto oder melde dich an, um zu kommentieren

Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...