Types/Wave/Noise.ps1
|
<# .SYNOPSIS Noise Generator .DESCRIPTION Generates a Noise at a `-Frequency`, for `-Duration`, at `-Volume` Mixes this tone with a `-Signal` and `-Noise` volume. #> [OutputType([double[]])] param( # The frequency [Alias('Hz')] [float]$Frequency = 440, # The amount of time to generate. [Timespan]$Duration = $( if ($this.BPM -is [TimeSpan]) {$this.BPM} else { [TimeSpan]::FromSeconds(60/128) } ), # The volume [float]$Volume = 0.5, # The volume of the signal (by default 0.6) [ValidateRange(0,1)] [double] $Signal = 0.60, # The volume of the noise (by default 0.4) [ValidateRange(0,1)] [double] $Noise = 0.40, # 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 bits per sample. # Will default to the `.BitsPerSample` of `$this` wave. # If there is no `$this` wave, will default to 4. [uint16]$BitsPerSample = $( if ($this.BitsPerSample) { $this.BitsPerSample } else { 4 } ), # 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 } ), # The audio format. # Will default to the `.AudioFormat` of `$this` wave. # If there is no `$this` wave, will default to 3 (IEEE floating point). [uint16]$AudioFormat = $( if ($this.AudioFormat) { $this.AudioFormat } else { 3 } ) ) $BytesPerSecond = $SampleRate * $channelCount * $BitsPerSample/8 # Cache our references, for the minor speed boost it may give us. $math = [Math] # Calculate the number of samples $numberOfSamples = $math::Round($Duration.TotalSeconds * $BytesPerSecond) # Our step size is the bits per sample / 8 $step = $BitsPerSample/8 # We can imagine each cycle as a series of circles # how many circles? Whatever our frequency may be. $cycle = 2 * $math::PI * $Frequency # The divisor will remain the same, so compute it now. $divisor = ($sampleRate * $channelCount * $step) $random = [Random]::new() # Generate one sample at a time. return ,[double[]]@(for ($i = 0; $i -lt $numberOfSamples; $i+=$step) { # Calculate the envelope $envelope = 1.0 - ($i / $numberOfSamples) # 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) $randomNoise = ($random.NextDouble() * 2) - 1 ( ($sample * $Signal) + ($randomNoise * $noise) ) * $Volume * $envelope }) |