Pythonで32bitfloatのWAVファイルが再生したい
結果
結論から言うと出来ました!ただ動作確認したのはLinuxからのみです。
ハイレゾ音源を再生したい
ZOOM社が販売しているフィールドレコーダー及びマイクトラックシリーズは32bitfloat機と呼ばれており、ゲイン調整無しで録音できます。しかしながら、これらの機種が使用している、超ハイレゾフォーマット(192kHz、32bitフロートのWAVファイル)への対応状況は様々です。音楽用の編集環境であるDAWはほぼ対応しているので編集作業は問題ないのですが、これをPythonからでも再生したりしたいので今回調べてみました。
よく使われるPythonのサウンドモジュールは、16bitまでは再生できるのですが、32bitとなると再生できない場合が多かったです。
pydub等色々試してみましたが音量がおかしくなりほぼダメでしたw(そのうち直るかも)
そんな中、紆余曲折しいろいろなモジュールを試してみた中で一番手軽に使える方法がわかったので記事にしました。
sounddeviceとsoundfileを組み合わせる
必要なパッケージは次のとおりです。
import sounddevice as sd
import soundfile as sf
ポイントとしては多くのファイル形式の読み込みに対応したsoundfileを使うことです。
このモジュールはかなり多彩なフォーマットをnumpyの行列に変換してくれます。
というわけで、簡単な再生関数は次の通り
32bitfloatで記録されたWAVファイル再生する
def playback(f):
data, fs = sf.read(f, dtype='float32')
sd.play(data, fs)
status = sd.wait()
たったこれだけで実現できました。24bitや32bitのWAVファイルが再生できます。
ZOOM社の32bitフロート機を持っている人などは是非ご活用ください。
おまけ(再生する場所を指定する方法)
soundfile
で読み込まれたdata
はnumpy.ndarray
になっているので再生する区間を指定する場合はこれをスライスで取り出すことが出来ます。ただし、サンプリングレートはファイルによって違うので秒数で指定する場合は少し計算する必要が有ります。
下の例はseconds
を指定した場合にファイルの先頭からその部分まで切り出しているデモです。
# 切り出す長さをmsecで表す
msec = seconds * 1000
data, fs = sf.read(f, dtype='float32')
# msec辺りのサンプリングレートに変換する
mfs = fs // 1000
# 最初のseconds秒のみ抜き出し
pdata = data[0:msec*mfs]
sd.play(pdata, fs)
status = sd.wait()
msec
に変換しているのは、細かい位置指定をする場合に対応するためです。
実際に使用した元の関数内ではseconds
は整数を想定されている部分なので、そのまま書いていますが、そこに小数を入れるとエラーになりますので注意です。
一秒以下まで指定する場合はmsec
を使って指定すれば細かく再生位置を指定することができます。