Анализируйте звук с помощью быстрого преобразования Фурье


109

Я пытаюсь создать графический анализатор спектра на Python.

В настоящее время я читаю 1024 байта 16-битного двухканального аудиопотока с частотой дискретизации 44 100 Гц и усредняю ​​амплитуду двух каналов вместе. Итак, теперь у меня есть массив из 256 короткометражных фильмов со знаком. Теперь я хочу предварительно сформировать fft для этого массива, используя такой модуль, как numpy, и использовать результат для создания графического анализатора спектра, который для начала будет иметь всего 32 бара.

Я прочитал статьи в Википедии о быстром преобразовании Фурье и дискретном преобразовании Фурье, но мне все еще неясно, что представляет собой результирующий массив. Вот как выглядит массив после того, как я преобразую fft в свой массив с помощью numpy:

   [ -3.37260500e+05 +0.00000000e+00j   7.11787022e+05 +1.70667403e+04j
   4.10040193e+05 +3.28653370e+05j   9.90933073e+04 +1.60555003e+05j
   2.28787050e+05 +3.24141951e+05j   2.09781047e+04 +2.31063376e+05j
  -2.15941453e+05 +1.63773851e+05j  -7.07833051e+04 +1.52467334e+05j
  -1.37440802e+05 +6.28107674e+04j  -7.07536614e+03 +5.55634993e+03j
  -4.31009964e+04 -1.74891657e+05j   1.39384348e+05 +1.95956947e+04j
   1.73613033e+05 +1.16883207e+05j   1.15610357e+05 -2.62619884e+04j
  -2.05469722e+05 +1.71343186e+05j  -1.56779748e+04 +1.51258101e+05j
  -2.08639913e+05 +6.07372799e+04j  -2.90623668e+05 -2.79550838e+05j
  -1.68112214e+05 +4.47877871e+04j  -1.21289916e+03 +1.18397979e+05j
  -1.55779104e+05 +5.06852464e+04j   1.95309737e+05 +1.93876325e+04j
  -2.80400414e+05 +6.90079265e+04j   1.25892113e+04 -1.39293422e+05j
   3.10709174e+04 -1.35248953e+05j   1.31003438e+05 +1.90799303e+05j...

Мне интересно, что именно представляют собой эти числа и как бы я преобразовал эти числа в процент от высоты для каждого из 32 столбцов. Кроме того, следует ли мне усреднять 2 канала вместе?

Ответы:


209

Показываемый вами массив - это коэффициенты преобразования Фурье аудиосигнала. Эти коэффициенты можно использовать для получения частотного содержания звука. БПФ определено для комплексных входных функций, поэтому получаемые вами коэффициенты будут мнимыми числами, даже если все ваши входные данные являются действительными значениями. Чтобы получить количество мощности на каждой частоте, вам необходимо вычислить величину коэффициента БПФ для каждой частоты. Это не просто действительная составляющая коэффициента, вам нужно вычислить квадратный корень из суммы квадрата его действительной и мнимой составляющих. То есть, если ваш коэффициент равен a + b * j, то его величина равна sqrt (a ^ 2 + b ^ 2).

После того, как вы вычислили величину каждого коэффициента БПФ, вам необходимо выяснить, какой звуковой частоте принадлежит каждый коэффициент БПФ. N-точечное БПФ даст вам частотную составляющую вашего сигнала на N равноотстоящих частотах, начиная с 0. Поскольку ваша частота дискретизации составляет 44100 выборок / сек. и количество точек в вашем FFT равно 256, ваш частотный интервал составляет 44100/256 = 172 Гц (приблизительно)

Первым коэффициентом в вашем массиве будет коэффициент частоты 0. Это в основном средний уровень мощности для всех частот. Остальные ваши коэффициенты будут отсчитываться от 0 с кратностью 172 Гц, пока вы не дойдете до 128. В БПФ вы можете измерять только частоты до половины ваших точек выборки. Прочитайте эти ссылки на Частота Найквиста и Найквиста-Шеннона сэмплирования теоремы , если вы мазохист и должны знать , почему, но основным результатом является то , что ваши низкие частоты будут воспроизведены или псевдонимами в высших ведер частот. Таким образом, частоты будут начинаться с 0, увеличиваться на 172 Гц для каждого коэффициента до коэффициента N / 2, затем уменьшаться на 172 Гц до коэффициента N - 1.

Этой информации должно быть достаточно, чтобы вы начали. Если вам нужно гораздо более доступное введение в БПФ, чем это дается в Википедии, вы можете попробовать Understanding Digital Signal Processing: 2nd Ed. . Мне это очень помогло.

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

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


1
В основном я могу найти в Интернете только слишком сложные объяснения БПФ, это было отличное и простое объяснение того, как количество точек выборки влияет на результаты БПФ. Спасибо тебе за это!
эхолокации

26

Хотя этой ветке уже много лет, я нашел ее очень полезной. Я просто хотел поделиться своим мнением со всеми, кто находит это и пытается создать что-то подобное.

Что касается деления на бары, это не следует делать, как предлагает antti, путем поровну деления данных в зависимости от количества баров. Наиболее полезным было бы разделить данные на октавные части, каждая октава в два раза больше частоты предыдущей. (т.е. 100 Гц - это на октаву выше 50 Гц, что на октаву выше 25 Гц).

В зависимости от того, сколько тактов вы хотите, вы делите весь диапазон на диапазоны октавы 1 / X. Основываясь на заданной центральной частоте A на полосе, вы получаете верхний и нижний пределы полосы из:

upper limit = A * 2 ^ ( 1 / 2X )
lower limit = A / 2 ^ ( 1 / 2X )

Чтобы вычислить следующую соседнюю центральную частоту, вы используете аналогичный расчет:

next lower =  A / 2 ^ ( 1 / X )
next higher = A * 2 ^ ( 1 / X )

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

Например: мы хотим разделить диапазоны на 1/3 октавы и начать с центральной частоты 1 кГц.

Upper limit = 1000 * 2 ^ ( 1 / ( 2 * 3 ) ) = 1122.5
Lower limit = 1000 / 2 ^ ( 1 / ( 2 * 3 ) ) =  890.9

Учитывая 44100 Гц и 1024 отсчета (43 Гц между каждой точкой данных), мы должны усреднить значения от 21 до 26 (890,9 / 43 = 20,72 ~ 21 и 1122,5 / 43 = 26,10 ~ 26)

(Полоса 1/3 октавы даст вам около 30 полос между ~ 40 Гц и ~ 20 кГц). Как вы уже понимаете, по мере того, как мы поднимаемся выше, мы будем усреднять больший диапазон чисел. Низкие столбцы обычно включают только 1 или небольшое количество точек данных. В то время как более высокие столбцы могут составлять в среднем сотни точек. Причина в том, что 86 Гц - это октава выше 43 Гц ... тогда как 10086 Гц звучат почти так же, как 10043 Гц.


10

у вас есть образец, длина которого по времени составляет 256/44100 = 0,00580499 секунды. Это означает, что ваше разрешение по частоте составляет 1 / 0,00580499 = 172 Гц. 256 значений, которые вы получаете из Python, соответствуют частотам, в основном, от 86 Гц до 255 * 172 + 86 Гц = 43946 Гц. Вы получаете комплексные числа (отсюда "j" в конце каждого второго числа).

ИЗМЕНИТЬ: ИСПРАВЛЕННАЯ НЕПРАВИЛЬНАЯ ИНФОРМАЦИЯ

Вам нужно преобразовать комплексные числа в амплитуду, вычислив sqrt (i 2 + j 2 ), где i и j - действительная и мнимая части, соответственно.

Если вы хотите иметь 32 бара, вы должны, насколько я понимаю, взять среднее значение четырех последовательных амплитуд, получив 256/4 = 32 бара, как вы хотите.


4
Обратите внимание: если c - комплексное число, sqrt (c.real 2 + c.imag 2) == abs (c)
tzot

0

БПФ возвращает N комплексных значений, которые из вас могут вычислить module=sqrt(real_part^2+imaginary_part^2). Чтобы получить значение для каждой полосы, вы должны просуммировать модули по всем гармоникам внутри полосы. Ниже вы можете увидеть пример анализатора спектра на 10 полосок. Код c должен быть обернут, чтобы получить модуль pyd python.

float *samples_vett;
float *out_filters_vett;
int Nsamples;
float band_power = 0.0;
float harmonic_amplitude=0.0;
int i, out_index;

out_index=0;


for (i = 0; i < Nsamples / 2 + 1; i++)       
        {
            if (i == 1 || i == 2 || i == 4 || i == 8 || i == 17 || i == 33 || i == 66 || i == 132 || i == 264 || i == 511)
            {
                out_filters_vett[out_index] = band_power; 
                band_power = 0; 
                out_index++;  
            }

            harmonic_amplitude = sqrt(pow(ttfr_out_vett[i].r, 2) + pow(ttfr_out_vett[i].i, 2));
            band_power += harmonic_amplitude;

        }

Я разработал и изготовил на Python целый анализатор спектра с 10 светодиодами. Вместо использования библиотеки nunmpy (слишком большой и бесполезной для получения только БПФ) был создан модуль python pyd (всего 27 КБ) для получения БПФ и разделения всего звукового спектра на полосы.

Кроме того, для чтения выходного аудио был создан модуль pyd loopback WASapi portaudio. Вы можете увидеть проект (блок-схему) на изображении 10BarsSpectrumAnalyzerWithWASapi.jpg

Только что добавил обучающее видео на свой канал на YouTube: как спроектировать и сделать очень умный Python Spectrum Analyzer 10 Led Bar

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.