Удаление шума (шипения) из аудиофайла Raw WAV с помощью Python


Я хочу удалить шум (шипение) из аудиофайла wave. Полный волновой звуковой график находится здесь:

Я использую код ниже. Это может быть глупая попытка, но в 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 = 'x00x00'
    else:
        #Keep the frame 
        final_frame = iframe
    op.writeframes(final_frame)
op.close()
ip.close()

После запуска вышеописанного скрипта он стал таким:

Шумовая часть (

С Наилучшими Пожеланиями,

2 2

2 ответа:

Ваша первая проблема заключается в том, что вы декодируете значения как big-endian, в то время как они на самом деле являются little-endian. Вы можете легко исправить это с помощью struct модуль . Я также добавил функцию abs, поскольку амплитуда обычно равна расстоянию от нуля, которое всегда положительно.

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

Это заставит ваш код делать то, что вы ожидаете. К сожалению, это не решает большую проблему, которая заключается в том, что это совершенно неправильный подход. Он не смотрит на саму форму волны, он смотрит только на один образец за раз. Простая синусоидальная волна, которая работает в полном масштабе, будет иметьМного образцов, которые ниже вашего порога, и вы внесете значительные искажения, установив их на ноль.

Действительно ли ваши данные подписаны или не подписаны? Если он подписан, то то, что вы хотите сделать, - это если абсолютное значение амплитуды

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

И если это правда, вам вообще не нужно изменять амплитуду.

Если это неподписанные данные, то ваш 0 действительно равен 32768. Вы можете преобразовать unsigned в signed, просто вычитая ваш цифровой 0:

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

Обратите внимание, что это дает вам диапазон между -32768..32767.

Если вы предпочитаете работать в без подписи вы можете сделать это так же легко. Но когда вы пишете кадр 0, запишите его в 32768, а не в 0, так как для беззнакового 0-это отрицательный максимум-очень большой сигнал.