Ответ 1
Ну, все зависит от того диапазона частот, который вам нужен. БПФ работает, беря 2 ^ n выборок и предоставляя вам 2 ^ (n-1) реальные и мнимые числа. Я должен признать, что я довольно туманна в отношении того, что именно представляют эти ценности (у меня есть друг, который обещал пройти все это со мной вместо кредита, который я ему сделал, когда у него были финансовые проблемы;)), кроме угол вокруг круга. Эффективно они предоставляют вам arccos параметра угла для синуса и косинуса для каждого частотного бункера, из которого исходные 2 ^ n выборок могут быть полностью восстановлены.
В любом случае это имеет огромное преимущество в том, что вы можете рассчитать величину, взяв эвклидовое расстояние реальной и мнимой частей (sqrtf ((real * real) + (imag * imag))). Это дает вам ненормализованное значение расстояния. Это значение затем можно использовать для создания величины для каждой полосы частот.
Итак, давайте возьмем порядок 10 БПФ (2 ^ 10). Вы вводите 1024 образца. Вы получаете FFT эти образцы, и вы возвращаете 512 мнимых и реальных значений (конкретный порядок этих значений зависит от используемого вами алгоритма FFT). Таким образом, это означает, что для аудиофайла 44,1 кГц каждый бит представляет собой 44100/512 Гц или ~ 86 Гц для каждого бункера.
Одна вещь, которая должна выделяться из этого, заключается в том, что если вы используете больше образцов (из того, что называется временем или пространственным доменом при работе с многомерными сигналами, такими как изображения), вы получаете лучшее частотное представление (в том, что называется частотной областью), Однако вы жертвуете одним за другого. Это как раз то, что происходит, и вам придется жить с ним.
В основном вам нужно будет настроить частотные модули и временное/пространственное разрешение, чтобы получить требуемые данные.
Сначала немного номенклатуры. Образцы времени 1024, о которых я упоминал ранее, называют вашим окном. Обычно, когда вы выполняете такой процесс, вы захотите сдвинуть окно на какую-то сумму, чтобы получить следующие 1024 отсчета, которые вы хотите FFT. Очевидным было бы сделать выборки 0- > 1023, затем 1024- > 2047 и т.д. Это, к сожалению, не дает лучших результатов. В идеале вы хотите в какой-то степени перекрывать окна, чтобы с течением времени добиться более плавного изменения частоты. Чаще всего люди сдвигают окно на половину размера окна. т.е. ваше первое окно будет 0- > 1023 второго 512- > 1535 и т.д. и т.д.
Теперь это вызывает еще одну проблему. Хотя эта информация обеспечивает идеальную обратную коррекцию FFT-сигнала, она оставляет вам проблему, которая в какой-то степени течет в объемные бункеры. Чтобы решить эту проблему, некоторые математики (гораздо более умные, чем я) придумали концепцию функции окна. Функция окна обеспечивает гораздо лучшую частотную изоляцию в частотной области, но приводит к потере информации во временной области (т.е. Ее невозможно полностью перестроить сигнал после того, как вы использовали оконную функцию AFAIK).
Теперь существуют различные типы оконной функции, начиная от прямоугольного окна (фактически ничего не делая с сигналом) до различных функций, которые обеспечивают гораздо лучшую изоляцию по частоте (хотя некоторые могут также убивать окружающие частоты, которые могут вас заинтересовать!!). Существует, увы, ни один размер не подходит для всех, но я большой поклонник (для спектрограмм) функции окна черманмана-гарриса. Я думаю, что это дает лучшие результаты!
Однако, как я упоминал ранее, FFT предоставляет вам ненормализованный спектр. Чтобы нормализовать спектр (после вычисления евклидова расстояния), вам нужно разделить все значения на коэффициент нормировки (я подробнее рассмотрю здесь).
эта нормализация даст вам значение от 0 до 1. Таким образом, вы можете легко увеличить это значение на 100, чтобы получить шкалу от 0 до 100.
Это, однако, не там, где оно заканчивается. Спектр, который вы получаете от этого, довольно неудовлетворен. Это потому, что вы смотрите на величину с использованием линейной шкалы. К сожалению, человеческое ухо слышит, используя логарифмический масштаб. Это довольно часто вызывает проблемы с тем, как выглядит спектрограмма/спектр.
Чтобы обойти это, вам нужно преобразовать эти 0 в 1 значения (я назову его "x" ) в шкалу децибел. Стандартное преобразование 20.0f * log10f (x), Затем это даст вам значение, при котором 1 преобразуется в 0 и 0, преобразуется в -infinity. ваши величины теперь находятся в соответствующем логарифмическом масштабе. Однако это не всегда полезно.
На этом этапе вам нужно изучить исходную глубину бита образца. При 16-битной выборке вы получаете значение, которое находится между 32767 и -32768. Это означает, что динамический диапазон - это fabsf (20.0f * log10f (1.0f/65536.0f)) или ~ 96.33dB. Итак, теперь мы имеем это значение.
Возьмите значения, которые мы получили из приведенного выше дБ. Добавьте это значение -96.33 к нему. Очевидно, максимальная амплитуда (0) теперь равна 96,33. Теперь он действует по тому же значению, и теперь у вас есть значение от -infinity до 1.0f. Закрепите нижний конец на 0, и теперь у вас есть диапазон от 0 до 1 и умножьте его на 100, и у вас есть конечный диапазон от 0 до 100.
И это намного больше монстра, чем я изначально предполагал, но должен дать вам хорошее обоснование того, как создать хороший спектр/спектрограмму для входного сигнала.
и дышать
Дальнейшее чтение (для людей, отличных от оригинального плаката, который уже нашел его):
Преобразование БПФ в спектрограмму
Изменить. В стороне я обнаружил, что поцелуй FFT намного проще в использовании, мой код для выполнения прямого fft выглядит следующим образом:
CFFT::CFFT( unsigned int fftOrder ) :
BaseFFT( fftOrder )
{
mFFTSetupFwd = kiss_fftr_alloc( 1 << fftOrder, 0, NULL, NULL );
}
bool CFFT::ForwardFFT( std::complex< float >* pOut, const float* pIn, unsigned int num )
{
kiss_fftr( mFFTSetupFwd, pIn, (kiss_fft_cpx*)pOut );
return true;
}