Быстрая свертка FFT: как применить окно, чтобы минимизировать потрескивание


Я пытаюсь сделать быструю свертку fft (размер блока fft=1024 выборки) из импульсная характеристика, связанная с головкой (L=512 отсчетов) с синусоидальной волной аудиосигнал. Здесь вы можете увидеть график импульсной реакции:

Http://fs2.directupload.net/images/150617/fc9j6cs7.png

Я разбил звуковой сигнал волны на блоки с размером блока M=513. Затем я обнулил каждый волновой блок и hrtf до 1024 образцов, применил fft, умножение и ifft. Вы можете увидеть результат один блок на следующем рисунке:

Http://fs1.directupload.net/images/150617/bxoe9fkm.png

После этого я сдвинул каждый блок 513 образцов на масштаб времени дальше последнего блока (размер прыжка = 0) и добавил его к старому блоку, что дало правильный свернутый вывод.

Здесь вы можете увидеть (упрощенную версию) кода python для 5 добавленных выходных блоков:

# set iteration counter to 0
blocknumber = 0 
# read in audio file
_, audiodata = scipy.io.wavefile.read("filename_audio_wave")
_, hrtf_block =  scipy.io.wavefile.read("filename_hrtf_wave")
while blocknumber <5:

    # set blocksizes
    fft_blocksize = 1024
    audio_blocksize = 513
    hrtf_blocksize = 512
    binaural = np.zeros((fft_blocksize*5, ), dtype=np.int16)

    # Do zeropadding: zeropad hrtf and audio
    hrtf_block_zeropadded = np.zeros((fft_blocksize, ), dtype = 'int16')
    hrtf_block_zeropadded[0:hrtf_blocksize, ] = hrtf_block
    sp_block_sp_zeropadded = np.zeros((fft_blocksize, ), dtype = 'int16')
    sp_block_sp_zeropadded[0:sp_blocksize, ] = audiodata[blocknumber*audio_blocksize : (blocknumber+1)*audio_blocksize, ]

    # bring time domain input to to frequency domain
    hrtf_block_fft = fft(hrtf_block_zeropadded, fft_blocksize)
    audio_block_fft = fft(audio_block_zeropadded, fft_blocksize)

    binaural_block_frequency = hrtf_block_fft * audio_block_fft
    binaural_block = ifft(binaural_block_frequency, fft_blocksize).real

    # add the block to the other blocks
    slide_forward_samples = 513
    binaural[blocknumber*slide_forward_samples : blocknumber*slide_forward_samples+fft_blocksize, ] += binaural_block
    blocknumber+=1

На следующем шаге я хотел свернуть каждый блок с помощью slighty different импульс реакция, которая привела к треску шума между блоками. Я обнаружил, что мне нужно применить окно и позволить свернутым блокам перекрываться. Я не знал, как именно это сделать. Не могли бы вы дать мне несколько советов?

Будем считать, что мы хотим достичь перекрытия в 50% и использовать окно Хэмминга.

    Правильно ли, что каждый блок должен содержать теперь 50% образцов предыдущего блока?
  • где я должен применить окно? Должен ли я применять его до того, как быстрое преобразование Фурье свертка на блоках звукового сигнала (размер окна: 513 сэмплов) или на вывод ifft (windowsize 1024: samples)?
  • и сколько выборок мне нужно, чтобы сдвинуть выходной сигнал fft на шкала времени с 50% перекрытием?

Большое Спасибо за вашу помощь

2 2

2 ответа:

Использование окна с перекрытием-добавление / сохранение быстрой свертки редко является правильным способом фильтрации. Но если вы хотите попробовать:

Обратите внимание, что последовательность окон фон-Ханна, смещенная на половину их длины, суммирует выигрыш в единицу, за исключением самого начала или конца.

Поэтому измените длину окна данных с 513 на 512, используйте смещение 256 (половина 512 для усиления unity), используйте окно фон Ханна (Хэмминг изменит усиление), накладку на что-либо по длине окна 512 плюс импульс длина ответа, и использовать перекрытие add / save с остатком (возможно, перенося хвост над несколькими сегментами окна ввода).

513 не годится, потому что ближайшее целое число к половинному смещению вызовет некоторую пульсацию в суммированном усилении всех перекрывающихся окон.

Вы также можете использовать смещение 1/4 окна, которое удвоит коэффициент усиления и отрегулирует этот коэффициент усиления в 2 раза при постобработке. и т.д.

Спасибо за помощь. Я расширил вход hrtf до 513 сэмплов и применил окно к входу синусоидального сигнала длиной 512 сэмплов. Это сработало.