Вопрос

У меня есть аудиофайл, и я перебираю его, беру 512 выборок на каждом этапе и затем пропускаю их через БПФ.

У меня есть данные в виде блока 514 с плавающей запятой (с использованием ippsFFTFwd_RToCCS_32f_I IPP) с чередованием реальных и мнимых компонентов.

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

const float realValue   = buffer[(y * 2) + 0];
const float imagValue   = buffer[(y * 2) + 1];
const float value       = sqrt( (realValue * realValue) + (imagValue * imagValue) );

Это дает что-то немного полезное, но я бы предпочел какой-то способ получить значения в диапазоне от 0 до 1.Проблема с вышеизложенным заключается в том, что пики в конечном итоге возвращаются к значению около 9 или более.Это означает, что все становится ужасно насыщенным, а затем появляются другие части спектрограммы, которые почти не проявляются, несмотря на то, что они кажутся довольно сильными, когда я пропускаю звук через спектрограмму прослушивания.Я полностью признаю, что не уверен на 100%, что представляют собой данные, возвращаемые БПФ (кроме того, что они представляют собой значения частоты блока длиной 512 выборок, который я передаю).Особенно мне не хватает понимания того, что именно представляет собой комплексное число.

Любые советы и помощь будут очень признательны!

Редактировать:Просто для уточнения.Моя большая проблема заключается в том, что возвращаемые значения БПФ бессмысленны без какого-либо представления о масштабе.Может ли кто-нибудь указать мне на разработку этого масштаба?

Редактировать2:Я получаю действительно красивые результаты, выполняя следующие действия:

size_t count2   = 0;
size_t max2     = kFFTSize + 2;
while( count2 < max2 )
{
    const float realValue   = buffer[(count2) + 0];
    const float imagValue   = buffer[(count2) + 1];
    const float value   = (log10f( sqrtf( (realValue * realValue) + (imagValue * imagValue) ) * rcpVerticalZoom ) + 1.0f) * 0.5f;
    buffer[count2 >> 1] = value;
    count2 += 2;
}

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

Есть ли что-то СЕРЬЕЗНО неправильное в том, что я делаю?

Это было полезно?

Решение

Обычно, чтобы увидеть все БПФ, нужно логарифмировать величину.

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

Другие советы

Для каждого окна из 512 выборок вы вычисляете величину БПФ, как вы это делали.Каждое значение представляет собой величину соответствующей частоты, присутствующей в сигнале.

mag
 /\
 |
 |      !         !
 |      !    !    !
 +--!---!----!----!---!--> freq
 0          Fs/2      Fs

Теперь нам нужно разобраться с частотами.

Поскольку входной сигнал имеет действительные значения, БПФ симметрично относительно середины (компонент Найквиста), причем первый член представляет собой компонент постоянного тока.Зная частоту дискретизации сигнала Fs, частота Найквиста равна Fs/2.И поэтому для индекса k, соответствующая частота k*Fs/512

Таким образом, для каждого окна длиной 512 мы получаем величины на указанной частоте.Группа из них в последовательных окнах образует спектрограмму.

Просто чтобы люди знали, что я проделал МНОГО работы над всей этой проблемой.Главное, что я обнаружил, это то, что БПФ требует нормализации после его выполнения.

Для этого вы усредняете все значения вашего вектора окна вместе, чтобы получить значение несколько меньше 1 (или 1, если вы используете прямоугольное окно).Затем вы делите это число на количество частотных элементов, которые у вас есть после преобразования БПФ.

Наконец, вы делите фактическое число, возвращаемое БПФ, на число нормализации.Ваши значения амплитуды теперь должны находиться в диапазоне от -Inf до 1.Журнал и т. д., как вам будет угодно.Вы по-прежнему будете работать с известным диапазоном.

Есть несколько вещей, которые, я думаю, вам пригодятся.

Прямое ПФ будет иметь тенденцию давать на выходе большие числа, чем на входе.Вы можете думать об этом как о том, что вся интенсивность с определенной частотой отображается в одном месте, а не распределяется по набору данных.Имеет ли это значение?Вероятно, нет, потому что вы всегда можете масштабировать данные в соответствии со своими потребностями.Однажды я написал пару БПФ/ОБПФ на основе целых чисел, и каждый проход требовал изменения масштаба, чтобы предотвратить переполнение целых чисел.

Реальные данные, которые вы вводите, преобразуются во что-то почти сложное.Оказывается, buffer[0] и buffer[n/2] реальны и независимы.Есть хорошее обсуждение этого здесь.

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

const float value = sqrt((realValue * realValue) + (imagValue * imagValue));

извлекает информацию об интенсивности, но отбрасывает информацию о фазе.Логарифмирование по сути просто ослабляет большие пики.

Надеюсь, это полезно.

Если вы получаете странные результаты, вам следует проверить документацию библиотеки БПФ, чтобы увидеть, как упаковываются выходные данные.Некоторые процедуры используют упакованный формат, в котором действительные/мнимые значения чередуются, или они могут начинаться с элемента N/2 и повторяться.

Для проверки работоспособности я бы предложил создать выборочные данные с известными характеристиками, например Fs/2, Fs/4 (Fs = частота выборки) и сравнить выходные данные процедуры БПФ с ожидаемыми.Попробуйте создать синус и косинус на одной и той же частоте, поскольку они должны иметь одинаковую величину в спектре, но разные фазы (т. е. RealValue/imagValue будут отличаться, но сумма квадратов должна быть одинаковой).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top