简体   繁体   中英

Remove Noise(hiss) from Raw WAV audio file using Python

I want to remove noise(hisss) from a wave audio file. The full wave audio graph is here :

I'm using below code. It might be a stupid attempt but in matlab i've noticed that the noise part's amplitude varies between 0-3000. So i tried to make all of them to zero and save new frames to a new wav file. Somehow it did not work!

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

After running above script it became this:

The noise part (<= 2500 ) is still present..So Please suggest how i can remove those unnecessary parts !

Best Regards,

Your first problem is that you're decoding the values as big-endian, while they're actually little-endian . You can fix that easily with the struct module . I've also added the abs function since amplitude is usually the distance from zero, which is always positive.

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

This will make your code do what you expect. Unfortunately it doesn't solve the larger problem, which is that this is the wrong approach entirely. It doesn't look at the waveform itself, it only looks at a single sample at a time. A simple sine wave that runs full scale will have many samples that are below your threshold, and you'll introduce significant distortion by setting them to zero.

Is your data really signed or unsigned? If it's signed, that what you want to do is if the absolute value of the amplitude is <3000 clamp to 0:

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

and if that's true, you don't need to modify the amplitude at all.

If it's unsigned data, then your 0 is really at 32768. You can convert unsigned to signed by simply subtracting your digital 0:

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

Note this gives you a range between -32768..32767.

If you prefer to work in unsigned, you can do that just as easily too. But when you write the 0 frame, write it to 32768, not 0, as for unsigned, 0 is the negative maximum - a very large signal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM