PowerShellでwaveファイルを作成したときに、System.IO.BinaryWriter の Write オーバーロードでやらかしたこと


BinaryWriter Class (System.IO) | Microsoft Docs

BinaryWriterは標準ライブラリにあるので、すぐ使えて便利ですが、ミスをしてしまいました。
こんな風に書くと16ビットではなく32ビット書き込まれてしまいました。

$bw.Write([int16]2 * 1)

そうならないように

$bw.Write([int16](2 * 1))

括弧でくくっています。

ファイルにwavファイルを書く例

. .\wave.ps1; $fs=[System.IO.File]::Create($pwd.Path+"\r.wav"); WriteWave($fs); $fs.Close();
wave.ps1
function WriteWave(
    [System.IO.Stream]$os
) {
    $bw = [System.IO.BinaryWriter]::new($os)
    $os.Position = 0
    $bw.Write([System.Text.Encoding]::ASCII.GetBytes("RIFF"))
    $os.Position = 8
    $bw.Write([System.Text.Encoding]::ASCII.GetBytes("WAVE"))
    $bw.Write([System.Text.Encoding]::ASCII.GetBytes("fmt "))

    $bw.Write([int32](16))
    $bw.Write([int16](1))
    $bw.Write([int16](1)) # 1モノラル 2ステレオ
    $bw.Write([int32](44100)) # 周波数
    $bw.Write([int32](44100 * 2 * 1)) # 44.1kHz 16bit モノラル

    $bw.Write([int16](2 * 1)) # 括弧ないと32ビット書かれる
    $bw.Write([int16](16))
    $bw.Write([System.Text.Encoding]::ASCII.GetBytes("data"))

    $samples = 44100 * 2; # 周波数 * 秒
    $size = $samples * 1 * 2  # 周波数 * 1モノラル * 16bit
    $bw.Write([int32]($size));

    for ($i = 0; $i -lt $samples; $i += 1) {
        $v = Get-Random -Minimum -32768 -Maximum 32768
        $bw.Write([int16]($v))
    }

    $os.Position = 4
    $bw.Write([int32]($os.Length - 8)) # 括弧ないと64ビット書かれる
}

waveファイルのフォーマットはこれを参考にしました。
wav ファイルフォーマット

PowerShellでバイナリファイルを扱うとき、BinaryWriterはすぐに使えて便利ですが、書き込まれる長さに注意が必要です。

WriteI16 とか WriteI32 のような
メソッド名と書き込むビット数が一致するメソッドを作るのがありかもしれません。