param([string]$OutputDirectory = (Join-Path $PSScriptRoot '..\Media\Sounds'))

$sampleRate = 44100

function Add-Tone {
    param([double[]]$Samples, [double]$Start, [double]$Duration, [double]$StartFrequency, [double]$EndFrequency, [double]$Amplitude, [double]$Attack = 0.012, [double]$Release = 0.18)
    $first = [int]($Start * $sampleRate)
    $count = [int]($Duration * $sampleRate)
    $phase = 0.0
    for ($index = 0; $index -lt $count; $index++) {
        $time = $index / [double]$sampleRate
        $progress = $index / [double][Math]::Max(1, $count - 1)
        $frequency = $StartFrequency + (($EndFrequency - $StartFrequency) * $progress)
        $phase += 2.0 * [Math]::PI * $frequency / $sampleRate
        $attackEnvelope = [Math]::Min(1.0, $time / [Math]::Max(0.001, $Attack))
        $releaseStart = [Math]::Max(0.0, $Duration - $Release)
        $releaseEnvelope = if ($time -le $releaseStart) { 1.0 } else { [Math]::Max(0.0, ($Duration - $time) / [Math]::Max(0.001, $Release)) }
        $envelope = $attackEnvelope * $releaseEnvelope * [Math]::Exp(-1.6 * $progress)
        $sampleIndex = $first + $index
        if ($sampleIndex -lt $Samples.Length) {
            $bell = (0.76 * [Math]::Sin($phase)) + (0.17 * [Math]::Sin(2.01 * $phase)) + (0.07 * [Math]::Sin(3.97 * $phase))
            $Samples[$sampleIndex] += $Amplitude * $envelope * $bell
        }
    }
}

function Write-Wave {
    param([string]$Path, [double[]]$Samples)
    $peak = 0.0
    foreach ($sample in $Samples) { $peak = [Math]::Max($peak, [Math]::Abs($sample)) }
    $gain = if ($peak -gt 0.0) { 0.82 / $peak } else { 1.0 }
    $dataLength = $Samples.Length * 2
    $stream = [System.IO.File]::Create($Path)
    try {
        $writer = [System.IO.BinaryWriter]::new($stream)
        $writer.Write([Text.Encoding]::ASCII.GetBytes('RIFF'))
        $writer.Write([int](36 + $dataLength))
        $writer.Write([Text.Encoding]::ASCII.GetBytes('WAVE'))
        $writer.Write([Text.Encoding]::ASCII.GetBytes('fmt '))
        $writer.Write([int]16); $writer.Write([int16]1); $writer.Write([int16]1)
        $writer.Write([int]$sampleRate); $writer.Write([int]($sampleRate * 2))
        $writer.Write([int16]2); $writer.Write([int16]16)
        $writer.Write([Text.Encoding]::ASCII.GetBytes('data')); $writer.Write([int]$dataLength)
        foreach ($sample in $Samples) {
            $value = [Math]::Tanh($sample * $gain) / [Math]::Tanh(0.82)
            $writer.Write([int16]([Math]::Round([Math]::Max(-1.0, [Math]::Min(1.0, $value)) * 32760.0)))
        }
        $writer.Flush()
    }
    finally { $stream.Dispose() }
}

New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null

$cleanse = [double[]]::new([int](0.82 * $sampleRate))
Add-Tone $cleanse 0.00 0.38 500 940 0.34 0.018 0.19
Add-Tone $cleanse 0.08 0.43 880 900 0.26 0.008 0.28
Add-Tone $cleanse 0.19 0.40 1320 1360 0.23 0.006 0.27
Add-Tone $cleanse 0.31 0.34 1760 1810 0.16 0.004 0.24
Add-Tone $cleanse 0.42 0.24 2360 2440 0.09 0.003 0.19
Write-Wave (Join-Path $OutputDirectory 'SlickUI_DebuffCleanseReady.wav') $cleanse

$ready = [double[]]::new([int](0.72 * $sampleRate))
Add-Tone $ready 0.00 0.34 659.25 659.25 0.30 0.010 0.22
Add-Tone $ready 0.00 0.28 329.63 329.63 0.12 0.012 0.18
Add-Tone $ready 0.19 0.43 987.77 987.77 0.34 0.008 0.31
Add-Tone $ready 0.19 0.36 493.88 493.88 0.13 0.010 0.25
Add-Tone $ready 0.30 0.30 1481.66 1481.66 0.10 0.005 0.24
Write-Wave (Join-Path $OutputDirectory 'SlickUI_AbilityReady.wav') $ready

Get-ChildItem -LiteralPath $OutputDirectory -Filter 'SlickUI_*.wav' | Select-Object FullName, Length
