Интенсивность полосы частот NAudio

#c# #algorithm #fft #naudio

#c# #алгоритм #БПФ #naudio

Вопрос:

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

У меня есть событие, инициируемое для каждого блока из 1024 выборок:

 public void Update(Complex[] fftResults)
{
   // ??
}
  

То, что я хотел бы иметь, — это массив чисел, указывающих интенсивность каждой полосы частот. Допустим, я хотел бы разделить окно на 16 полос.

Например, когда басовых частот больше, это может выглядеть так:

 ░░░░░░░░░░░░░░░░
▓▓▓░░░░░░░░░░░░░
▓▓▓░░░░░░░░░░░░░
▓▓▓▓░░░░░░░░░░░░
▓▓▓▓▓░░░░░░░░░░░
▓▓▓▓▓▓▓▓░░░▓░░▓░
  

Что я должен поместить в этот обработчик событий, если это возможно с этими данными?

Поступающие данные (Complex[] ) уже преобразованы с помощью БПФ. Это стереопоток.

Первая попытка:

 double[] bandIntensity = new double[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

public void Update(Complex[] fftResults)
{
    // using half fftResults because the others are just mirrored
    int band = 0;
    for (int n = 0; n < fftResults.Length/2; n  )
    {
        band = (int)(.5 * n / fftResults.Length * bandIntensity.Length);
        bandIntensity[band]  = Math.Sqrt(fftResults[n].X * fftResults[n].X   fftResults[n].Y * fftResults[n].Y);
        bandIntensity[band] /= 2;
    }
}
  

Вышесказанное кое-что делает, но я думаю, что слишком много внимания уделяется первым двум полосам, и я играю shakira, у которой не так много басов.

Спасибо!

Ответ №1:

Есть две отдельные проблемы, которые вы, вероятно, захотите рассмотреть здесь:

(1) Функция окна

Вам необходимо применить оконную функцию к вашим данным до БПФ, иначе вы получите спектральную утечку, что приведет к очень размытому спектру. Одним из неприятных побочных эффектов спектральной утечки является то, что если у вас есть какой-либо значительный компонент постоянного тока (0 Гц), то это приведет к форме 1 / f, которую вы видите на своей гистограмме.

(2) Логарифмические оси амплитуды / частоты

Человеческий слух по существу логарифмичен как по интенсивности, так и по частоте. Не только это, но речь и музыка, как правило, имеют больше энергии в низкочастотной части спектра. Чтобы получить более приятное и осмысленное отображение зависимости интенсивности от частоты, мы обычно делаем оси амплитуды и частоты логарифмическими. В случае оси амплитуд об этом обычно заботятся путем построения полной шкалы dB re, т.е.

 magnitude_dB = 10 * log10(magnitude);
  

В случае частотной оси вы, вероятно, захотите сгруппировать свои ячейки в диапазоны, каждый из которых может составлять октаву (частотный диапазон 2: 1) или, чаще, для более высокого разрешения, третью октаву. Итак, если вам просто нужны 10 «баров», вы можете использовать следующие октавные полосы:

    25 -    50 Hz
   50 -   100 Hz
  100 -   200 Hz
  200 -   400 Hz
  400 -   800 Hz
  800 -  1600 Hz
 1600 -  3200 Hz
 3200 -  6400 Hz
 6400 - 12800 Hz
12800 - 20000 Hz
  

(предполагается, что у вас частота дискретизации 44,1 кГц и верхний предел на вашем оборудовании для ввода звука составляет 20 кГц).

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

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

1. Для окна я вижу, что используется BlackmannHarrisWindow . Однако я еще не пробовал 10xLog10(), я посмотрю, как это изменит график. И я удалю ячейку постоянного тока 0 Гц.

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

3. ХОРОШО — и вы уверены , что применяется оконная функция ? Может быть, вы можете опубликовать больше кода, возможно, в новом вопросе — было бы неплохо увидеть ту часть, где вы настраиваете входной буфер, а затем вызываете оконную функцию FFT.

4. подойдет, просто нужно добраться до моего ноутбука

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