Как извлечь полуточные частоты из файла WAV, используя преобразования Фурье - PullRequest
12 голосов
/ 21 мая 2010

Допустим, у меня есть файл WAV. В этом файле представлена ​​серия синусоидальных сигналов с точными интервалами в 1 секунду. Я хочу использовать библиотеку FFTW для извлечения этих тонов в последовательности. Это особенно сложно сделать? Как бы я пошел по этому поводу?

Кроме того, каков наилучший способ записи тонов такого рода в файл WAV? Я предполагаю, что мне понадобится только простая звуковая библиотека для вывода.

Мой язык выбора - C

Ответы [ 3 ]

22 голосов
/ 22 мая 2010

Чтобы получить спектр мощности раздела вашего файла:

  • собрать N выборок, где N - это степень 2 - если ваша частота дискретизации составляет, например, 44,1 кГц, и вы хотите производить выборку приблизительно каждую секунду, тогда выберите N = 32768 выборок.

  • применить подходящую оконную функцию к образцам, например, Хеннинг

  • передать оконные сэмплы в подпрограмму FFT - в идеале вы хотите БПФ от реального к сложному, но если все, что у вас есть, это БПФ от сложного к сложному, тогда передайте 0 для всех мнимые части ввода

  • вычислите квадратичную величину выходных лотков БПФ (re * re + im * im)

  • (необязательно) вычислите 10 * log10 каждого квадрата выходного бина величины, чтобы получить значение величины в дБ

Теперь, когда у вас есть спектр мощности, вам просто нужно определить пик (и), который должен быть довольно простым, если у вас есть разумное отношение сигнал / шум. Обратите внимание, что разрешение по частоте улучшается с увеличением N. Для приведенного выше примера частоты дискретизации 44,1 кГц и N = 32768 разрешение по частоте каждого бина составляет 44100/32768 = 1,35 Гц.

3 голосов
/ 27 мая 2010

Вас в основном интересует оценка спектра - при условии, что вы уже прошли этап чтения WAV и преобразования его в сигнал с дискретным временем.

Среди различных методов самым основным является периодограмма, которая сводится к выполнению оконного дискретного преобразования Фурье (с БПФ) и сохранению его квадратичной величины. Это соответствует ответу Павла. Вам нужно окно, которое охватывает несколько периодов самой низкой частоты, которую вы хотите обнаружить. Пример: если ваши синусоиды могут иметь частоту до 10 Гц (период = 100 мс), вы должны взять окно от 200 мс до 300 мс или около того (или больше). Однако периодограмма имеет некоторые недостатки , хотя ее легко вычислить и более чем достаточно, если не требуется высокая точность:

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

Периодограмма может работать лучше, усредняя несколько окон, с необоснованным выбором ширины ( Метод Бартлета ). И есть много других методов оценки спектра (AR моделирование).

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

2 голосов
/ 21 мая 2010

WAV-файлы содержат данные с линейной кодовой модуляцией (LPCM) . Это просто означает, что это последовательность значений амплитуды с фиксированной частотой дискретизации. Заголовок RIFF содержится в начале файла для передачи такой информации, как частота дискретизации и биты на выборку (например, 16-бит со знаком 8 кГц).

Формат очень прост, и вы можете легко свернуть свой собственный. Однако есть несколько библиотек, доступных для ускорения процесса, таких как libsndfile . Простой Direct-media Layer (SDL) / SDL_mixer и PortAudio - две удобные библиотеки для воспроизведения.

Что касается подачи данных в FFTW, вам потребуется буферизовать 1-секундные порции (определить размер по частоте дискретизации и битам на выборку). Затем преобразуйте все сэмплы в IEEE с плавающей точкой (т.е. float или double в зависимости от конфигурации FFTW - libsndfile может сделать это за вас). Затем создайте другой массив для хранения выходных данных частотной области. Наконец, создайте и выполните план FFTW, передав оба буфера в fftw_plan_dft_r2c_1d и вызвав fftw_execute с возвращенным дескриптором fftw_plan .

...