Repository navigation
set_Samples
James Brundage edited this page Oct 23, 2026
·
1 revision
This changes the wave.
Parameters
The new samples
| required | type | position | pipeline | wildcard | aliases |
|---|---|---|---|---|---|
| false | Double[] | 1 | false | false |
View Source
<#
.SYNOPSIS
Sets Wave Samples
.DESCRIPTION
Sets the samples in the Wave.
This changes the wave.
#>
param(
# The new samples
[double[]]
$Samples
)
$BitsPerSample =
if ($this.BitsPerSample) { $this.BitsPerSample }
else { 32 }
$audioFormat =
if ($this.AudioFormat) { $this.AudioFormat }
else { 3 }
$sampleNumber = 0
$progress = [Ordered]@{
Id = Get-Random
Status = " "
Activity = "Encoding "
}
[byte[]]$CurrentData = $this.Data
# Classic "looking glass" problem
# We can avoid writing samples twice faster than re-encoding
# _if_ decoding takes us less time than just encoding over it.
# So first check for our cached property of samples
# and then see if the current data block is less than a megabyte
# If either of these is true, use the current samples.
if ($this.'#Samples'.Length -or
$CurrentData.Length -lt 512kb
) {
[double[]]$CurrentSamples = $this.Samples
} else {
# Otherwise, set the current samples to null
# (which effectively avoids the logic to skip samples)
[double[]]$CurrentSamples = $null
}
[int]$BlockSize = $BitsPerSample / 8
[byte[]]$NewData = @(
foreach ($sample in $samples) {
#region Encode Sample
if ($sampleNumber -and -not ($sampleNumber % 32kb)) {
$progress.Status = "$sampleNumber / $($Samples.Length)"
$progress.PercentComplete = ($sampleNumber * 100 / $samples.Length)
Write-Progress @progress
}
# If we already have samples
if ($sampleNumber -lt $CurrentSamples.Length -and (
# and this sample did not change
($CurrentSamples[$sampleNumber] -eq $sample)
)) {
# we can skip encoding and just output the original bytes.
$CurrentData[
($sampleNumber * $BlockSize)..(
(($sampleNumber + 1) * $BlockSize) - 1
)
]
# advance our sample number
$sampleNumber++
continue # and continue.
}
$sampleNumber++
# If we are using 32-bit floating point audio
if ($BitsPerSample -eq 32 -and $audioFormat -eq 3) {
# we are basically done.
<#
No clamping required.
Well, not technically speaking.
[float] has a max value of `3.402823E+38`.
Attempting to play volume at this level will likely be limited physically,
and would likely damage speakers and eardrums far before this volume could be achieved.
#>
# So we will just cast to float,
[BitConverter]::GetBytes([float]$sample) # get the bytes,
continue # and continue
}
# If we are dealing with whole number audio formats,
# We've got to clamp it down to an amplitude between -1 and 1.
# Unfortunately, `Clamp` is not part of older .NET framework versions
# So we will clamp the old-fashioned way, with an `if`
if ($sample -gt 1) { $sample = 1 }
elseif ($sample -lt -1) { $sample = -1 }
# If there are 8 bits per sample
if ($BitsPerSample -eq 8) {
# round each sample into bytes, with 127 as the zero point.
[byte][Math]::Floor(
127 + $sample * 127
)
}
# If there are 16 bits per sample
elseif ($BitsPerSample -eq 16) {
# we just need to scale an `[int16]`
# Hardcode `[int16]::MaxValue` for speed
[BitConverter]::GetBytes([int16]($sample * 32767))
}
# If there are 32 bits per sample
elseif ($BitsPerSample -eq 32) {
# we can just scale to an `[int32]`.
# Hardcode `[int32]::MaxValue` for speed
[BitConverter]::GetBytes([int32]($sample * 2147483647))
}
#endregion Encode Sample
}
)
$progress.Remove('PercentComplete')
$progress.Completed = $true
Write-Progress @progress
# Set our new data
$This.Data = $newData
# This will invalidate our samples,
# so cache the sample data we just passed.
$this |
Add-Member NoteProperty '#Samples' $samples -Force
return $this
If you like making waves, please star this repo and consider sponsoring