使用Python从原始WAV音频文件中去除噪音(嘶嘶声)

3 投票
2 回答
5899 浏览
提问于 2025-04-18 01:01

我想从一个波形音频文件中去掉噪音(嘶嘶声)。完整的波形音频图在这里:

我正在使用下面的代码。可能这听起来有点傻,但在matlab中我注意到噪音部分的幅度在0到3000之间。所以我试着把它们都变成零,然后把新的帧保存到一个新的wav文件里。结果不知道为什么没有成功!

import wave
import sys
ip = wave.open(sys.argv[1], 'r')

op = wave.open(sys.argv[2], 'w')
op.setparams(ip.getparams())

for i in range(ip.getnframes()):
    iframes = ip.readframes(1)
    amp = int(iframes.encode('hex'),16)
    if amp > 32767:
        amp = 65535 - int(iframes.encode('hex'),16)#-ve
        print amp
    else:
        amp = int(iframes.encode('hex'),16)#+ve
        print amp
    if amp < 2000:
        #make it zero
        final_frame = '\x00\x00'
    else:
        #Keep the frame 
        final_frame = iframe
    op.writeframes(final_frame)
op.close()
ip.close()

运行上面的脚本后,结果变成了这样:

噪音部分(小于等于2500)仍然存在……所以请告诉我我该怎么去掉这些多余的部分!

最好的祝愿,

2 个回答

0

你的数据到底是有符号的还是无符号的呢?如果是有符号的,那你想做的事情就是,如果振幅的绝对值小于3000,就把它限制为0:

if abs(amplitude) < 3000:
    final_frame = '\x00\x00'

如果这个条件成立,你就不需要对振幅进行任何修改。

如果是无符号数据,那么你的0实际上是32768。你可以通过简单地减去你的数字0来把无符号数据转换为有符号数据:

amp = int(iframe.encode('hex'),16)
amp -= amp - 32768

这样做会给你一个范围,从-32768到32767。

如果你更喜欢使用无符号数据,也可以这样做。但当你写0帧的时候,要写成32768,而不是0,因为在无符号数据中,0是负的最大值——一个非常大的信号。

2

你的第一个问题是,你在解码的时候使用了大端字节序,但实际上它们是小端字节序。你可以通过使用struct模块来轻松解决这个问题。我还添加了abs函数,因为音量通常是从零的距离,这个值总是正数。

amplitude = abs(struct.unpack('<h', iframe))

这样你的代码就能按照预期工作了。不幸的是,这并没有解决更大的问题,那就是这种方法根本就是错的。它没有查看波形本身,而只是一次查看一个样本。一个完整的正弦波会有很多样本低于你的阈值,这样会导致你把它们设置为零,从而引入明显的失真。

撰写回答