Как ресэмплировать аудио, используя FFT или DFT

12

Я выбрал голосовое аудио, сначала выполнив БПФ, затем взяв только те части результата, которые мне нужны, и затем выполнив обратное БПФ. Тем не менее, он работает должным образом только тогда, когда я использую частоты, которые обе имеют степень двойки, скажем, понижающую дискретизацию с 32768 до 8192. Я выполняю БПФ для данных 32k, отбрасываю верхние 3/4 данных и затем выполняю обратное БПФ на оставшиеся 1/4.

Однако всякий раз, когда я пытаюсь сделать это с данными, которые не совпадают должным образом, происходит одно из двух: библиотека математики, которую я использую (Aforge.Math), выбрасывает соответствие, потому что мои образцы не имеют степени двойки. Если я попытаюсь заполнить сэмплы нулями, чтобы они стали степенью двойки, на другом конце это вылетит. Я также попытался использовать DFT вместо этого, но в итоге он оказался безумно медленным (это нужно делать в режиме реального времени).

Как бы я собирался правильно обнулить данные FFT, как на начальном, так и на обратном FFT в конце? Предполагая, что у меня есть сэмпл с частотой 44,1 кГц, который должен быть на 16 кГц, я сейчас пробую что-то вроде этого, сэмпл размером 1000.

  1. Pad вводит данные до 1024 в конце
  2. Выполнить БПФ
  3. Считайте первые 512 элементов в массив (мне нужны только первые 362, но нужны ^ 2)
  4. Выполнить обратное БПФ
  5. Считайте первые 362 элемента в буфер воспроизведения аудио

Из этого я получаю мусор в конце. Выполнение того же действия, но без необходимости дополнения на шаге 1 и 3 из-за сэмплов, уже являющихся ^ 2, дает правильный результат.


источник
9
БПФ действительно не правильный способ сделать это. Вам нужен многофазный набор фильтров для максимальной эффективности, но если вы просто хотите решить проблему, сначала увеличьте частоту дискретизации до GCD, затем низкочастотную, а затем уменьшите частоту.
Бьорн Роше
Привет Бьорн: что такое "GCD"?
SpeedCoder5

Ответы:

16

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

22*32*52*7227*5332*7225*5

Предыдущие шаги должны быть выполнены независимо от того, как вы хотите выполнить повторную выборку данных. Теперь поговорим о том, как это сделать с помощью БПФ. Хитрость повторной выборки с помощью БПФ состоит в том, чтобы выбирать длины БПФ, чтобы все работало хорошо. Это означает выбор длины FFT, кратной скорости прореживания (в данном случае 441). Для примера давайте выберем длину БПФ 441, хотя мы могли бы выбрать 882, или 1323, или любое другое положительное кратное 441.

Чтобы понять, как это работает, это помогает визуализировать это. Вы начинаете с аудиосигнала, который в частотной области выглядит примерно так, как показано на рисунке ниже. Частота дискретизации 44,1 кГц

Когда вы закончите обработку, вы захотите уменьшить частоту дискретизации до 16 кГц, но вам нужно как можно меньше искажений. Другими словами, вы просто хотите сохранить все от изображения выше от -8 кГц до +8 кГц и отбросить все остальное. Это приводит к изображению ниже. введите описание изображения здесь

Обратите внимание, что частоты выборки не в масштабе, они просто для иллюстрации концепций.

25*5

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

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

  2. LL-1нули (обратите внимание, что количество выборок данных и количество выборок заполнения должны ОБА положительно кратно коэффициенту прореживания - вы можете увеличить длину заполнения, чтобы удовлетворить этому ограничению), FFT'ит заполненные данные, умножая частотную область данные и фильтр, а затем наложение высокочастотных (> 8 кГц) результатов на низкочастотные (<8 кГц) результаты, прежде чем отбрасывать высокочастотные результаты. К сожалению, поскольку фильтрация в частотной области сама по себе является большой темой, я не смогу более подробно остановиться на этом ответе. Я скажу, однако, что если вы фильтруете и обрабатываете данные более чем в одном блоке, вам нужно будет реализовать Overlap-and-Add или Overlap-and-Save, чтобы сделать фильтрацию непрерывной.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ. Разница между начальным числом выборок в частотной области и целевым числом выборок в частотной области должна быть равномерной, чтобы можно было удалить то же количество выборок с положительной стороны результатов, что и с отрицательной стороны результатов. В нашем примере начальным числом выборок была частота прореживания, или 441, а целевым числом выборок была скорость интерполяции, или 160. Разница составляет 279, что не является четным. Решение состоит в том, чтобы удвоить длину FFT до 882, что приводит к удвоению целевого числа выборок до 320. Теперь разница четная, и вы можете без проблем отбрасывать соответствующие выборки в частотной области.

Джим Клэй
источник
Очень хорошо. Как ты делаешь такие красивые фигуры на лету, Джим?
Spacey
@ Мохаммед Я обычно использую Powerpoint. В этом случае я использовал версию Powerpoint Libre Office, которая, как мне кажется, называется «Impress».
Джим Клэй
Здравствуйте, у меня есть вопрос по вашей точке (2). Что вы имеете в виду именно на этом шаге: «... и затем наложение высокочастотных (> 8 кГц) результатов вниз на низкочастотные (<8 кГц) результаты перед падением высокочастотных результатов». Я понимаю шаги до этого. После того, как я умножу свои данные f-домена на f-домен моего фильтра, что тогда? Кроме того, работает ли этот метод, если вы хотите также повысить частоту ваших данных? Спасибо.
TheGrapeBeyond
@TheGrapeBeyond Когда вы используете псевдоним во временной области, вы добавляете все зоны Найквиста вместе. Первые элементы всех зон Найквиста объединяются и становятся новым первым элементом первой зоны Найквиста. Второй элемент всех зон Найквиста суммируется и становится новым вторым элементом первой зоны Найквиста и т. Д.
Джим Клэй,
Хм, я не уверен, что понимаю, как вы делаете FFT на основе пересэмплирования, потому что, когда я пробую это здесь, я получаю очень странные результаты. Я сделаю вопрос об этом.
TheGrapeBeyond
3

Хотя приведенный выше ответ действительно завершен:

Вот суть этого:

  1. чтобы уменьшить сигнал, он должен быть целым числом. Перед понижением частоты сигнала необходимо отфильтровать сигнал.
  2. Вы можете добиться рациональной понижающей дискретизации числа, сначала увеличивая частоту дискретизации / интерполируя сигнал.
  3. Апсэмплинг просто вставляет нули, а затем фильтрует сигнал.
  4. так, чтобы достичь 3/4 частоты дискретизации. увеличить сигнал, вставив 4 нуля между каждой выборкой сигнала. Примените фильтр. Затем отфильтруйте сигнал и удалите каждые 3 из каждых 4 выборок сигнала.

Подробности об этом:

http://www.ws.binghamton.edu/fowler/fowler%20personal%20page/EE523_files/Ch_14_1%20Subband%20Intro%20&%20Multirate%20(PPT).pdf

Кроме того: если только это не является абсолютно необходимым, НЕ компьютер FFT, чтобы затем вычислить IFFT. Это невероятно медленный процесс и считается неподходящим для большинства задач обработки сигналов. БПФ обычно используется для анализа проблемы или применения обработки сигнала только в частотной области.

Кибермужчины
источник
1

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

1 - принять желаемый векторный сигнал длины N.

2 - Выполнить N точку БПФ.

3 - Нулевое заполнение FFT с 160 * N нулями в середине вектора FFT.

4 - Выполнить IFFT

5 - Выберите один из 441 образцов, отбрасывая остальные 440.

У вас останется вектор длиной N * 160/441, который будет вашим преобразованным сигналом.

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

Надеюсь, поможет.

кость
источник