NumPy FFT 乘法的运行时警告

Runtime Warnings on multiplication of NumPy FFT

我正在尝试按照 this 比较 .wav 文件的方法,但收到以下警告:

valid:call.py:23: RuntimeWarning: overflow encountered in multiply
  mult = numpy.multiply(fft1, fft2)
call.py:23: RuntimeWarning: invalid value encountered in multiply
  mult = numpy.multiply(fft1, fft2)

我检查发生了什么,发现 mult 设置如下:

[[ inf -0.j  nan-infj  nan+infj ...,  nan+infj  nan-infj  nan+infj]
 [ inf -0.j -inf+nanj  inf+nanj ..., -inf+nanj  inf+nanj -inf+nanj]
 [ inf -0.j  nan-infj  inf+nanj ...,  nan-infj  inf+nanj  nan+infj]
 ..., 
 [ inf -0.j -inf+nanj -inf+nanj ..., -inf+nanj -inf+nanj -inf+nanj]
 [ inf -0.j -inf+nanj -inf+nanj ..., -inf+nanj -inf+nanj -inf+nanj]
 [ inf -0.j  nan-infj  nan-infj ...,  nan+infj  nan+infj  nan+infj]]

按照 dsp.stackexchange 上的回答指示,我正在用零填充我的数据。这会导致无穷大吗?我如何乘复数列表?

更新: 我已将其更改为 "manually" 像这样相乘:

mult = [i*j for (i, j) in itertools.izip(fft1, fft2)]

并且 nan-inf 越来越少,但仍然有一些。它现在产生以下警告:

valid:call.py:26: RuntimeWarning: overflow encountered in cdouble_scalars
  mult = [i*j for (i, j) in itertools.izip(a, b)]
call.py:26: RuntimeWarning: invalid value encountered in cdouble_scalars
  mult = [i*j for (i, j) in itertools.izip(a, b)]

不过好像更近了。有什么想法吗?

更新 2 当然,我已经忘记了我打开 wav 块的 kluge 方式。我做了一个sys.getsizeof(frames[0])发现每个元素的大小都是36。代码在这里:

def get_fft(fft_path):
    return_list = []
    frames_list = []
    chunk_size = 36
    start = 0
    wav = wave.open(fft_path, 'r')
    frames = wav.readframes(wav.getnframes())
    wav.close()

    while start+chunk_size < len(frames):
            data = struct.unpack(">fdddd", frames[start:start+chunk_size])
            frames_list.extend(data)
            start += chunk_size
            if len(frames_list) >= 1000:
                    frames_list.extend(numpy.zeros(len(frames_list)))
                    return_list.append(numpy.fft.fft(frames_list))
                    frames_list = []

    return return_list

问题很可能出在这里:data = struct.unpack(">fdddd", frames[start:start+chunk_size])。字符串 ">fdddd" 告诉解压到 "get" 小尾数法 (>) 一个四字节浮点数 (f) 和四个八字节双精度数 (d)。我很可能误解了 documentation.

OP 解决方案: 正如@rth 和@Claris 猜测我错误地解包了我的数据。 运行 sys.getsizeof() 关于 frames 的元素让我相信每个元素都必须以 36 字节块的形式解包。

如另一个答案(我丢失了)所示:),我不得不将帧解压缩为更小的块:

data = struct.unpack(">fdddd", frames[start:start+chunk_size])

我改为:

data = struct.unpack(">H", frames[start:start+chunk_size])

然后我将 chunk_size 从 36 更改为 2。元素乘法现在工作正常,没有 NaNs 或 Infs。

更多信息见struct.unpack()