LoginSignup
1
4

More than 5 years have passed since last update.

numpy.ndarrayの絶対値で詰まった話

Last updated at Posted at 2017-06-08

最近、音声ファイルに対してちょっとした操作を行っています。

こちらのページを参考に、16bit整数のnumpy.ndarray型として読み込んでみました。

Pythonで音の波形を表示(Wavファイル)

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()

ダウンロード (2).png

対処方法

これは、最初の読み込みで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
1
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4