Удаление шума (шипения) из аудиофайла 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 ответа:
Ваша первая проблема заключается в том, что вы декодируете значения как 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-это отрицательный максимум-очень большой сигнал.