Types/Wave/Sweep.ps1
|
<# .SYNOPSIS Wave Sweep .DESCRIPTION Generates a Wave that sweeps between two frequencies. #> [OutputType([double[]])] param( # The frequency. # If no frequency is provided, it will be 440hz (A4) [Alias('Hz')] [float]$Frequency = 0, # The destination frequency. # If not provided, will be half of the frequency [Alias('Hz2')] [float]$ToFrequency = 0, # The number of steps in the sweep # If none are provided, the frequencies will change continously [int]$StepCount = 0, # The duration to generate. [Timespan]$Duration = $( if ($this.BPM -is [TimeSpan]) {$this.BPM} else { [TimeSpan]::FromSeconds(60/128) } ), # The volume. # If the current wave has set a `volume`, # will use that volume. # Otherwise, will default to 0.5 [float]$Volume = $( if ($this.Volume) { $this.Volume } else { 0.5 } ), # The sample rate. # Will default to the `.SampleRate` of `$this` wave. # If there is no `$this` wave, will default to 44100 [uint32]$SampleRate = $( if ($this.SampleRate) { $this.SampleRate } else { 44100 } ), # The channel count. # Will default to the `.ChannelCount` of `$this` wave. # If there is no `$this` wave, will default to 1 (mono). [uint16]$channelCount = $( if ($this.ChannelCount) { $this.ChannelCount } else { 1 } ) ) if ($Frequency -eq 0) { $Frequency = 440 } if ($ToFrequency -eq 0) { $ToFrequency = $Frequency / 2 } # Calculate the number of samples $numberOfSamples = [Math]::Round($Duration.TotalSeconds * $SampleRate * $channelCount) $stepFrequency = if ($stepCount) { ($ToFrequency-$Frequency)/$StepCount } else { 0 } # The divisor will remain the same, so compute it now. $divisor = ($sampleRate * $channelCount) # We will return the wave as a `[double[]]`, # and preceeed it by a comma so that we return all samples at once. return ,[double[]]@( # Generate one sample at a time. for ($i = 0; $i -lt $numberOfSamples; $i++) { $t = $i/$numberOfSamples # Calculate the envelope $envelope = 1.0 - $t $currentFrequency = if ($StepCount) { $Frequency + ($stepFrequency * [Math]::Floor($t * $StepCount)) } else { $Frequency + ($ToFrequency - $Frequency) * $t } # We can imagine each cycle as a series of circles # how many circles? Whatever our frequency may be. $cycle = 2 * [math]::pi * $currentFrequency # Calculate the angle at this point in time (in radians) $angle = ($cycle * $i) / $divisor # The sample at this moment is the sine of that angle $sample = [Math]::Sin($angle) # We will scale this by the volume, and then by the envelope. $sample * $Volume * $envelope } ) |