#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.. Просто нужно сгенерировать столбцы!