我正在使用scipy.signal来过滤用pysoundfile导入的wav文件。我已经成功地使用filtfilt执行阶数为2和4的高通滤波器,并使用sosfilt执行阶数为2的高通滤波器,但当我指定阶数为4时,sosfilt失败:
第一个月
我写了下面的代码来演示这个问题。
import soundfile
import numpy
import scipy
def butter_highpass_sosfilt(data, lowcut, fs, order=2):
return scipy.signal.sosfilt(*scipy.signal.butter(order, [lowcut], fs=fs, btype='high', output='sos'), data)
def butter_highpass_filtfilt(data, lowcut, fs, order=1):
return scipy.signal.filtfilt(*scipy.signal.butter(order, [lowcut], fs=fs, btype='high', output='ba'), data)
audio, samplerate = soundfile.read("Test Audio.wav") #This is 24bit 44100 PCM
output1 = numpy.zeros((numpy.size(audio[:,0]),2))
output1[:,0] = butter_highpass_filtfilt(audio[:,0], 160, samplerate, order=2)
output1[:,1] = butter_highpass_filtfilt(audio[:,1], 160, samplerate, order=2)
soundfile.write("test output 1.wav", output1, samplerate, 'PCM_24')
output2 = numpy.zeros((numpy.size(audio[:,0]),2))
output2[:,0] = butter_highpass_filtfilt(audio[:,0], 160, samplerate, order=4)
output2[:,1] = butter_highpass_filtfilt(audio[:,1], 160, samplerate, order=4)
soundfile.write("test output 2.wav", output2, samplerate, 'PCM_24')
output3 = numpy.zeros((numpy.size(audio[:,0]),2))
output3[:,0] = butter_highpass_sosfilt(audio[:,0], 160, samplerate, order=2)
output3[:,1] = butter_highpass_sosfilt(audio[:,1], 160, samplerate, order=2)
soundfile.write("test output 3.wav", output3, samplerate, 'PCM_24')
output4 = numpy.zeros((numpy.size(audio[:,0]),2))
output4[:,0] = butter_highpass_sosfilt(audio[:,0], 160, samplerate, order=4)
output4[:,1] = butter_highpass_sosfilt(audio[:,1], 160, samplerate, order=4)
soundfile.write("test output 4.wav", output4, samplerate, 'PCM_24')
字符串
Output1、output2和output3都写入wav文件并按预期播放。程序在写入output4之前停止,并出现以下错误:
Traceback (most recent call last):
File "M:\Documents\Python\DSP try\Sosfilt error mre\Sosfilt error mre.py", line 29, in <module>
output4[:,0] = butter_highpass_sosfilt(audio[:,0], 160, int(samplerate/3), order=4)
File "M:\Documents\Python\DSP try\Sosfilt error mre\Sosfilt error mre.py", line 6, in butter_highpass_sosfilt
return scipy.signal.sosfilt(*scipy.signal.butter(order, [lowcut], fs=fs, btype='high', output='sos'), data)
File "C:\Users\edwar\AppData\Local\Programs\Python\Python311\Lib\site-packages\scipy\signal\_signaltools.py", line 4277, in sosfilt
x_zi_shape[axis] = 2
TypeError: only integer scalar arrays can be converted to a scalar index
型
2条答案
按热度按时间vqlkdk9b1#
对于阶数4,
scipy.signal.butter
返回形状为(2,6)
的数组。这是一个长度为 * 2 * 的序列。
当你用
*
操作符将序列 * 解压缩到一个函数调用中时,数组的两个元素(数组行)将分散在调用的第一个 * 和第二个 * 参数上。然后所有进一步的参数都“向下移动一个”。* 这就是问题所在。此处不应使用用于解包的
*
。*您的
data
参数在解包过程中被沿着,然后替换sosfilt()
的axis
参数。axis参数需要一个整数,而不是
data
。这个函数似乎感觉到了这个参数的“麻木”,并试图理解它。它可能是一个 * 零 * 维
np.ndarray
?如果是的话,这是可以接受的。但它不是,它有尺寸。错误消息如下:TypeError: only integer scalar arrays can be converted to a scalar index
这里的关键词是“scalar arrays”。“整数”在这里是次要的。我们还没查到那一步。
字符串
这是一个标量数组如果您为
axis
参数传递该值,则函数会很高兴(直到它看到42,这是一个令人震惊的轴数)。如果你传递
np.array([42])
,它会抛出同样的错误消息,因为它有维度,也就是说,一个维度的大小为1。形状为(1,)
。在
axis
参数的位置传递的值,即data
,* 肯定 * 有维数。这一切都是因为无害的解包
*
将一个序列变成了两个参数。我不得不写这个答案,因为另一个答案的解释是错误的。是的,修正是正确的(我建议
*
运算符是问题所在),但这并不能使 * 解释 * 正确。不涉及元组。不存在“单一价值”。解包对任何类型的序列都有效。numpy数组是序列。
butter()
返回numpy数组。是的,它是一个单一的对象,但在这里,它也是一个序列,解包操作符喜欢序列。这部分没有失败。8iwquhpp2#
正如Christoph正确指出的那样,问题出在
*a_tuple
符号上。该函数返回单个值,而不是元组,这会破坏代码。
字符串
更正版本:
型