Импульсный отклик, связанный с головкой, для бинаурального звука

#python #audio #signal-processing #fft #acoustics

#python #Аудио #обработка сигналов #бпф #акустика

Вопрос:

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

Пожалуйста, посмотрите прилагаемый скриншотвведите описание изображения здесь

Подробное описание того, что происходит:

Здесь принимается экспоненциальный сигнал развертки и воспроизводится обратно через громкоговоритель. Воспроизведение записывается с помощью микрофона. Записанный сигнал расширяется с использованием заполнения нулем (возможно, вдвое больше исходной длины), а также расширяется исходный сигнал экспоненциальной развертки. БПФ берутся для обоих (расширенной записи и расширенного оригинала), их БПФ делятся, и мы получаем функцию передачи номера. Наконец, выполняется обратный БПФ и выполняется некоторое управление окнами для получения импульсной характеристики.

Мой вопрос:

У меня возникли трудности с реализацией этой диаграммы на python. Как бы вы разделили два БПФ? Возможно ли это? Вероятно, я могу выполнить все шаги, такие как заполнение нулем и бпф, но, думаю, я не иду правильным путем. Я не понимаю оконный и отбрасывающий вариант второй половины.

Пожалуйста, может ли кто-нибудь с его / ее знаниями показать мне, как я мог бы реализовать это на python с помощью сигнала развертки? Простой небольшой пример также поможет получить представление о нескольких графиках. Пожалуйста, помогите.

Источник этого изображения: http://www.four-audio.com/data/MF/aes-swp-english.pdf

Заранее спасибо, Санкет Джейн

Комментарии:

1. как и при написании программного обеспечения в целом, одним из подходов было бы сначала решить более простую проблему, а затем подняться на холм сложности позже… введите известный сигнал, скажем, синусоидальную волну, в ваш код FFT, чтобы преобразовать данные из временной области в частотную… постройте график как входного, так и выходного сигнала, чтобы подтвердить, что вы можете правильно определить ту же частоту на выходе из вызова FFT, которую вы вводите в качестве частоты источника… затем используйте этот сигнал домена freq в качестве входного сигнала для обратного вызова FFT, который должен выводить временную область, очень похожую на синусоидальную волну вашего исходного источника… как только работа начнет усложняться

2. когда вы учитесь писать код, речь идет не о достижении решения, а о том, чтобы научиться решать проблемы и избегать использования библиотек или других готовых решений, которые вам не помогут… вместо этого самостоятельно создавайте алгоритмы (за исключением, возможно, вызова FFT ) … фактически, я рекомендую вам самостоятельно создать свой собственный код обратного БПФ с нуля без каких-либо библиотек… обучение программированию похоже на изучение математики, все о слоях знаний, и переход через слой оставит пробел в ваших знаниях… цель состоит в том, чтобы не было таких пробелов на пути от вопроса к решению

Ответ №1:

Да, разделение двух спектров БПФ возможно и на самом деле довольно легко реализовать на python (но с некоторыми оговорками). Проще говоря: поскольку свертка двух временных сигналов соответствует умножению их спектров, наоборот, деконволюция может быть реализована путем разделения спектров.

Вот пример простой деконволюции с помощью numpy:

( x это ваш сигнал развертки возбуждения и y записанный сигнал развертки, из которого вы хотите получить импульсную характеристику.)

 import numpy as np
from numpy.fft import rfft, irfft

# define length of FFT (zero padding): at least double length of input
input_length = np.size(x)
n = np.ceil(np.log2(input_length))   1
N_fft = int(pow(2, n))

# transform 
# real fft: N real input -> N/2 1 complex output (single sided spectrum)
# real ifft: N/2 1 complex input -> N real output
X_f = rfft(x, N_fft)
Y_f = rfft(x, N_fft)

# deconvolve
H = Y_f / X_f

# backward transform
h = irfft(H, N_fft)

# truncate to original length
h = h[:input_length]
 

Это простое решение практично, но его можно (и нужно) улучшить. Проблема в том, что вы получите повышение минимального уровня шума на тех частотах, где X_f имеет низкую амплитуду. Например, если ваша экспоненциальная синусоидальная развертка начинается со 100 Гц, для частотных диапазонов ниже этой частоты вы получаете деление (почти) на ноль. Одно из простых возможных решений этого — сначала инвертировать X_f, применить фильтр ограничения полосы пропускания (highpass lowpass), чтобы удалить «области усиления», а затем умножить его на Y_f:

 # deconvolve
Xinv_f = 1 / X_f
Xinv_f = Xinv_f * bandlimit_filter
H = Y_f * Xinv_f
 

Что касается искажения:
Приятным свойством экспоненциальной синусоидальной развертки является то, что создание гармонических искажений во время измерения (например, из-за нелинейностей в громкоговорителе) приведет к меньшим «побочным» откликам перед «основным» откликом после деконволюции (см. Это для более подробной информации).). Эти побочные отклики являются продуктами искажения и могут быть просто удалены с помощью временного окна. Если нет задержки «основного» ответа (начинается с t = 0), эти побочные ответы появятся в конце всего iFFT, поэтому вы удаляете их, закрывая вторую половину.

Я не могу гарантировать, что это на 100% правильно с точки зрения теории сигналов, но я думаю, что это показывает суть, и это работает 😉

Комментарии:

1. Большое спасибо за код. Теперь мой вопрос заключается в том, что я получил импульсный отклик комнаты, но с более высокими амплитудами, например, 5000 или 10000. Насколько я понял, амплитуды импульсной характеристики помещения варьируются от -1 до 1. Как мне это сделать? Я попытался нормализовать его, но правильно ли это?

Ответ №2:

Это немного выше моей головы, но, возможно, следующие советы могут помочь.

Во-первых, я наткнулся на очень полезный пример кода, представленный в книге Стива Смита «Руководство ученого и инженера по цифровой обработке сигналов«. Это включает в себя ряд операций, от основ свертки до самого алгоритма БПФ. Пример кода написан на BASIC, а не на Python. Но БАЗОВЫЙ отлично читается и должен быть легко переведен.

Я не совсем уверен в конкретном вычислении, которое вы описываете, но многие операции в этой области (при работе с несколькими сигналами), оказывается, просто используют сложение или вычитание составляющих элементов. Чтобы получить авторитетный ответ, я думаю, вам повезет больше на форуме по обработке сигналов Stack Overflow или на одном из форумов, связанных с DSP.

Если вы получите ответ в другом месте, было бы неплохо либо повторить его здесь, либо полностью удалить этот вопрос, чтобы уменьшить беспорядок.