Rustでwavファイルのライブラリを作りました

作りました(かなり前に)

https://github.com/yoshiyuki-koyama/wav_f64vec

もともとは開発中(といいつつ止まり気味)の自作GUIアプリの一部として描いていたのですが、ライブラリ化しようということで、バグ修正してテストを記述してライブラリとして独立させました。

この記事書いた時点ではv0.4.0です。というかこのバージョンになってからもかなり時間が経ってます。

未解決の課題:PCMの量子化の方法

2023/4/21追記:

下記の、PCMの整数値(format id = 1)と浮動小数点(format id = 3)の変換について、考え方1でSigned 16bitを-32768を浮動小数点の-1.0にすれば、整数値の数値表現と浮動小数点の仮数部の数値表現が合い、それが自然だと思われるので現状(v0.5.0)では、そうしています。

—–追記ここまで——

このライブラリにはwavファイルの読み書きのほかに、整数値のPCMからVec<Vec<f64>>に相互変換変換する機能を持たせてありますが、その変換で疑問が出てきました。

浮動小数点で表したときは-1.0と+1.0が一応の絶対値の最大値となります(それ以上の値も取れるけど)。整数値のPCMの場合、Signed 16bitなら-32768~+32767と1だけですがマイナスのほうが絶対値が大きくなります。

なので、ここをどう変換したらいいのかという疑問です。

下記、Signed 16bitのときを考えます(-32768~+32767)。

考え方1

+32767を+1.0、または、-32768を-1.0とするとき。

現状、v0.4.0では16bitの場合、32767が1.0になるようにしています。 下記のような感じです。

Signed 16bit-1.0~1.0へ変換した値浮動小数点の範囲
-32767-1.0-32767.5/32767より大きい、-32766.5/32767以下(※)
-1-1/32768-1.5/32767より大きい、-0.5/32767以下
00.0-0.5/32767より大きい、0.5/32767未満
+11/327671.5/32767以上、2.5/32767未満
+327671.032766.5/32767以上、32767.5/32767未満(※)

※実際には絶対値1.0以上は-32767と+32767になる。

このやり方だと、-32768は変換後は-1より小さくなります。 逆に、-32768を-1.0へ変換するとすると、+32767は小数点に変換したとき 32767/32768 となり1.0に届きません。

数値計算だとこっちが自然な気がします。。。

考え方2

Signed 16bitで0になる範囲を、0.0以上、1/32768未満と考えます。 すると下記のようになります。

Signed 16bit浮動小数点の範囲
-32768-1.0以上、-32767/32768未満(※)
-1-1/32768以上、0.0未満
00.0以上、1/32768未満
+11/32768以上、2/32768未満
+3276732767/32768以上、1.0未満(※)

※実際には絶対値1.0以上は-32768と+32767になる。

最小値、最大値の絶対値の違いは、以上か未満かの差だけになります。

A/D変換とかUnsignedの場合を考えると、こっちの方が自然な気がする。。。

そもそも

考え方以前に決まってる気がします。どこかに情報ないかな?

ライブラリの設計について

GUIアプリで使いたかったのでVec<Vec<f64>>に変換する機能を作ってあったり、サンプリングレート変換機能がありますが、他の類似ライブラリと比較すると蛇足だなと思いました。

まとめ

ライブラリ化することでテストの記述など含めて勉強になりました。

今は事情によりプログラミングから少し離れていますが、そのうち再開させたいですね。

Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です