最近、音声ファイルに対してちょっとした操作を行っています。
こちらのページを参考に、16bit整数のnumpy.ndarray
型として読み込んでみました。
import numpy as np
import wave
def read_wavefile(filename):
"""wav形式のファイルをnumpy.ndarrayとして読み込む"""
wf = wave.open(filename , 'r')
buf = wf.readframes(wf.getnframes())
# バイナリデータを16bit整数に変換
return np.frombuffer(buf, dtype='int16')
こちらの音声の絶対値を取りたかったため、numpy.absolute
で配列を変換します。
arr = read_wavefile('test.wav')
arr_abs = np.absolute(arr)
ところが、この中の-32768
という値が、正の値に変換されずに残ってしまっています。
ヒストグラムを取ると、他の負の値はプラスになっているものの、-32768
だけが残ってしまっていることがわかります(値が細かいですが)。
import matplotlib.pyplot as plt
print(type(arr_abs))
# => <class 'numpy.ndarray'>
print(arr_abs.min())
# => -32768
plt.hist(np.absolute(arr), bins=100)
plt.show()
対処方法
これは、最初の読み込みで32bit整数として読み込むと解決しました。
def read_wavefile(filename):
"""wav形式のファイルをnumpy.ndarrayとして読み込む"""
wf = wave.open(filename , 'r')
buf = wf.readframes(wf.getnframes())
# バイナリデータを32bit整数に変換
arr = np.frombuffer(buf, dtype='int16')
return arr.astype(np.int32)
arr = read_wavefile('test.wav')
arr_abs = np.absolute(arr)
print(arr_abs.min())
# => 0
これはおそらく、16bit整数は-32768から32767までしか表現できないため、numpy.absolue
で符号を変換した値が変換できず、そのままの値が出力されてしまっているということだと思います。
(これらの仕様について詳しく書いてあるドキュメントは見つかりませんでしたが)
PythonのnumpyやR言語などの数値計算用のプログラムを利用する際は、高速化のためにC言語のデータ型をそのまま用いていることが多いので、普段より注意が必要だということを改めて認識しました。
ちなみに今回用いたnumpy
のバージョンは1.13.0です。
$ pip freeze | grep numpy
numpy==1.13.0