如何在python中找到原始wav文件中带有噪声的子波文件的位置?

问题描述 投票:0回答:1

原始wav文件长度为20分钟。
sub wav 文件的长度为 20-40 秒。
1分钟内找到位置。

我尝试使用

scipy.io.wavfile
将文件读取为 numpy 数组,并使用强力找到差异最小的位置。花了很多时间,没有输出正确的位置。

from scipy.io import wavfile
import numpy as np
import tqdm
_, sub = wavfile.read('video_6_1_filtered.wav')
_, origin = wavfile.read('video6.wav')
for i in tqdm.tqdm(range(0, len(origin)-len(sub)):
    temp = np.sum(np.absolute(np.subtract(origin[i:i+len(sub)],sub)))
    if temp < minv:
        minv = temp
        index = i
print(i,minv)
python numpy audio scipy
1个回答
0
投票

这里有一些问题。

首先,存在逻辑错误。当您搜索匹配项时,您会存储最佳匹配位置。然而,当你打印结果时...

print(i,minv)

...您正在打印循环变量

i
,这是您尝试的最后一个位置,而不是第一个。这个应该是
print(index, minv)

我没有检查这是否有效 - 进度条告诉我需要 36 小时来测试。

就性能而言,有一种更快的方法来比较这些。具体来说,您可以使用

scipy.signal.correlate()
来关联两个信号,这实际上是尝试在每个可能的偏移处将两个信号相乘。然后,您在该卷积中寻找峰值,如下所示。

enter image description here

对于大信号,执行此卷积的时间复杂度为 O(N log N)。相比之下,在每个偏移处减去两个信号的时间复杂度为 O(N^2)。

我使用以下代码来查找匹配项:

# from scipy.io import wavfile
import scipy
import numpy as np
import matplotlib.pyplot as plt
import tqdm
sub_sr, sub = scipy.io.wavfile.read('video_6_1_filtered.wav')
origin_sr, origin = scipy.io.wavfile.read('video6.wav')
assert sub_sr == origin_sr, "Sample rates differ - must be resampled to consistent sample rate"
correlation = scipy.signal.correlate(origin.astype('float32'), sub.astype('float32'), mode='valid')
index = np.argmax(correlation)
plt.plot(origin[index:index+len(sub), 0])
plt.show()
plt.plot(sub[:, 0])
plt.show()
scipy.io.wavfile.write('video6_subset.wav', origin_sr, origin[index:index+len(sub)])

这会找到最接近的匹配,并绘制它和参考信号。

备注:

  • 对于提供的信号(15 分钟长的 44 kHz 立体声 wav 文件),在我的计算机上需要 11 秒才能完成此关联。您可以通过将信号转换为单声道或下采样到较低的采样率来进一步加快速度。

  • 两个信号的采样率必须匹配。如果不匹配,那么对两个信号进行卷积将找不到它们匹配的位置。函数

    scipy.signal.resample
    对此很有用。

  • 我将两个信号都转换为 float32 - 否则它似乎将卷积的值限制为 int16 的最大值。

  • 通过实验,此方法适用于您提供的示例。

    但是,请记住,这比较的是时域中的信号,而不是频域中的信号。信号在时域中可能非常不同,而在频域中却非常相似,尤其是在音频经过几种不同方式处理的情况下。在比较声音时,人类大多在频域中听到它们。

© www.soinside.com 2019 - 2024. All rights reserved.