Проаналізуйте звук за допомогою швидкого перетворення Фур'є


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

Показаний масив - це коефіцієнти перетворення Фур'є в аудіосигналі. Ці коефіцієнти можна використовувати для отримання частотного вмісту звуку. FFT визначається для складних вхідних функцій введення, тому коефіцієнти, які ви отримаєте, будуть уявними числами, хоча всі ваші вхідні дані - це реальні значення. Для того щоб отримати кількість потужності в кожній частоті, потрібно обчислити величину коефіцієнта FFT для кожної частоти. Це не просто реальна складова коефіцієнта, потрібно обчислити квадратний корінь суми квадрата його реальної та уявної складових. Тобто, якщо ваш коефіцієнт дорівнює + b * j, то його величина дорівнює sqrt (a ^ 2 + b ^ 2).

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

Першим коефіцієнтом у вашому масиві буде коефіцієнт частоти 0. Це в основному середній рівень потужності для всіх частот. Решта ваших коефіцієнтів підраховуватиметься від 0 у кратних 172 Гц, поки ви не досягнете 128. У FFT ви можете вимірювати частоти до половини ваших вибіркових балів. Прочитайте ці посилання на Частота Найквіста і Найквиста-Шеннона семпліювання теореми , якщо ви мазохіст і повинні знати , чому, але основним результатом є те , що ваші низькі частоти будуть відтворені або псевдонімами в вищих відер частот. Тож частоти починатимуться від 0, збільшуватимуться на 172 Гц для кожного коефіцієнта до коефіцієнта N / 2, потім зменшуватимуться на 172 Гц до коефіцієнта N - 1.

Це має бути достатньо інформації для початку роботи. Якщо ви хочете набагато доступнішого ознайомлення з FFT, ніж це наведено у Вікіпедії, ви можете спробувати Розуміння цифрової обробки сигналів: 2nd Ed. . Мені це було дуже корисно.

Отже, це те, що представляють ці числа. Перетворення на відсоток висоти можна здійснити шляхом масштабування кожної частоти компонентної величини на суму всіх величин компонентів. Хоча це дало б лише представлення відносного розподілу частоти, а не фактичну потужність для кожної частоти. Ви можете спробувати масштабування на максимальну можливу величину частотної компоненти, але я не впевнений, що це відображатиметься дуже добре. Найшвидший спосіб знайти працездатний коефіцієнт масштабування - експериментувати над гучними та м'якими звуковими сигналами, щоб знайти правильну настройку.

Нарешті, вам слід усереднити два канали разом, якщо ви хочете показати частотний вміст усього аудіосигналу в цілому. Ви змішуєте стерео-аудіо в моно-аудіо і показуєте комбіновані частоти. Якщо ви хочете два окремих дисплея для правої та лівої частот, вам знадобиться виконати перетворення Фур'є на кожному каналі окремо.


1
Я в основному можу знайти лише надмірно складні пояснення FFT в Інтернеті, це було чудовим і простим поясненням того, як кількість вибіркових балів впливає на результати FFT. Дякую за це!
ехолокація

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

FFT повертає N комплексних значень, хто з вас може обчислити module=sqrt(real_part^2+imaginary_part^2). Щоб отримати значення для кожного діапазону, ви повинні підсумувати модулі про всі гармоніки всередині діапазону. Нижче ви можете побачити приклад про аналізатор спектру 10 барів. Код c повинен бути завернутий, щоб отримати модуль pyt 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;

        }

Я розробив і зробив цілий 10 світлодіодний аналізатор спектра барів Python. Замість того, щоб використовувати бібліотеку nunmpy (занадто велику і марну, щоб отримати лише FFT), був створений модуль python pyd (всього 27 КБ), щоб отримати FFT і розділити весь звуковий спектр на смуги.

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

Щойно додав підручник на моєму каналі YouTube: як створити та зробити дуже розумний аналізатор спектру Python 10 Led

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.