KissFFT (от kiss_fftr до kiss_fftri) — Как реконструировать исходный сигнал?

У меня возникли проблемы с пониманием того, как правильно использовать KissFFT (1.2.9). Все, чего я пытаюсь добиться на данный момент, это выполнить БПФ, а затем немедленно выполнить iFFT, чтобы снова восстановить исходный сигнал. Фрагмент кода ниже демонстрирует, что я делаю:

void test(short* timeDomainData, int length)
{
    // Create the configurations for FFT and iFFT...
    kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length, 0, NULL, NULL );
    kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length, 1, NULL, NULL );

    // Allocate space for the FFT results (frequency bins)...
    kiss_fft_cpx* fftBins = new kiss_fft_cpx[ length / 2 + 1 ];

    // FFT...
    kiss_fftr( fftConfiguration, timeDomainData, fftBins );

    // iFFT...
    kiss_fftri( ifftConfiguration, fftBins, timeDomainData );
}

Я обнаружил, что это на самом деле падает во время выполнения. Я обнаружил, что, разделив размер на 2 при создании конфигураций KissFFT, я остановил сбой:

kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length / 2, 0, NULL, NULL );
kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length / 2, 1, NULL, NULL );

Однако, когда я проигрываю реконструированные аудиоданные, они в основном тихие со странным потрескиванием.

Может кто-то указать мне верное направление?

Большое спасибо, П

Изменить 1: вот как я включаю заголовочный файл KissFFT и определяю переменную FIXED_POINT:

#define FIXED_POINT 16
#include "kiss_fftr.h"

Это гарантирует, что тип typedef 'kiss_fft_scalar' будет принудительно установлен на int16_t (short).

Изменить 2: целевой платформой является Android, поэтому я также добавил в свой файл Android.mk следующее:

LOCAL_CPPFLAGS += -DFIXED_POINT

person protectedmember    schedule 07.06.2012    source источник


Ответы (3)


Я заметил, что вы пришли в шортах. Вы уверены, что скомпилировали все для использования int16_t в качестве типа данных? Иногда несоответствие сред препроцессора может вызвать проблему.

Кроме того, версия с фиксированной точкой масштабируется вниз в обоих направлениях (вперед,инв). Поэтому, если вы хотите восстановить свой сигнал, вам нужно будет умножить все на nfft. Я бы рекомендовал умножать на насыщенность в два этапа.

например если вы выполняете БПФ+ОБПФ размером 1024, то умножьте на 32 после БПФ, а затем еще раз на 32 после ОБПФ.

person Mark Borgerding    schedule 08.06.2012
comment
Марк – Я действительно надеялся, что ты ответишь. Я уверен, что установил правильный тип данных, я обновил свой исходный пост с примером кода того, как я включаю заголовок KissFFT и определяю переменную FIXED_POINT. (Я обновил исходный пост, потому что эти комментарии не позволяют мне добавлять фрагменты кода). Пара вопросов: Что я должен умножать? А как вы вывели значение 32? Мой размер БПФ 16384... Спасибо, П. - person protectedmember; 08.06.2012
comment
Привет, Марк, хотя я очень ценю твой вклад, я все еще не понимаю твоего ответа? - person protectedmember; 11.06.2012
comment
Извините, что наткнулся на это, но у меня все еще нет ответа. Я понимаю, что масштабирование должно иметь место, но я не понимаю, не могу найти ответ и в ваших ответах не описано, что нужно масштабировать и на сколько. Ответы на большинство вопросов, циркулирующих в Интернете о Kiss FFT и масштабировании, читались ли вы ReadMe?... Отметьте, если вы написали библиотеку, не могли бы вы предоставить фрагмент кода, который выполняет БПФ на массиве шортов? а затем iFFT для восстановления исходного сигнала? Спасибо, П - person protectedmember; 28.06.2012
comment
Данные должны быть масштабированы. Поскольку БПФ являются линейными, вы можете математически сделать это до или после БПФ или ОБПФ. Однако при обработке с фиксированной точкой вы не сможете масштабировать значения без переполнения и представлять значения в ограниченном диапазоне. Именно поэтому я предлагаю разбить масштабирование на этапы. - person Mark Borgerding; 29.06.2012
comment
Это не случай написания моего кода для меня - меня это вполне устраивает, спасибо. Однако вы выпустили Kiss FFT, и у многих с этим проблемы. Простое написание Read Me и непрямые ответы на прямые вопросы только запятнают репутацию библиотеки. Я собираюсь нанести последний удар, иначе мне придется использовать другую библиотеку, как и многим другим людям в той же лодке, что и я. - person protectedmember; 01.07.2012

Я не уверен насчет тишины, но если вы получаете много потрескивания, это может быть связано с тем, что вы обрабатываете соседние блоки независимо, а не используете Overlap-Add, где вы эффективно плавно переходите между каждым блоком, чтобы получить более плавную характеристику.

person the_mandrill    schedule 08.06.2012
comment
если он не манипулирует данными в частотной области, то не должно быть разрывов на границах буфера. - person Mark Borgerding; 08.06.2012
comment
Это правда. Однако после реализации некоторых фильтров или преобразований может потребоваться добавление с перекрытием. Однако в данном случае это не объясняет щелчки. Тот факт, что вызов БПФ дает сбой, говорит о том, что размер одного из буферов неверен. Nfft больше длины? - person the_mandrill; 08.06.2012
comment
Ах, да, перекрытие-добавление... Я знаком с этой техникой, хотя надеюсь, что мне не понадобится ее использовать. Пользователю разрешено изменять следующие частоты: 31,5, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000 (ISO 1/3 октавы). Под капотом я сглаживаю значения интервалов частоты между 16 (1 до 31,5) и 20000 Гц (1 после 16000). Итак, если пользователь не может ничего изменить до 31.5 или после 16000, мне все еще нужно перекрывать-добавлять? - person protectedmember; 08.06.2012
comment
Я не уверен, я немного заржавел в Overlap-Add. Если вы просто выполняете простую фильтрацию, она может вам не понадобиться. Если вы выполняете анализ и реконструкцию сигнала (как я делал в прошлом), то O-A дает гораздо лучшие результаты, так как позволяет эффективно интерполировать кадры. - person the_mandrill; 09.06.2012
comment
Если вы напрямую меняете значения в частотной области, тогда да, вам нужно добавить перекрытие (или что-то еще, чтобы смягчить явление Гибба). Но это не заданный вопрос. - person Mark Borgerding; 10.06.2012

Я изо всех сил пытаюсь сделать то же самое в Android, но еще не получил его (см. ">здесь!), но я вижу проблему в вашем коде: "fftBins" должен иметь размер "length". Причина в том, что это необработанное преобразование, а не амплитуда/фаза частоты... Я думаю? Или я ошибся?

person cmbryan    schedule 09.06.2012
comment
Ах, коллега-разработчик заблудился посреди преобразований Фурье! Теперь я чувствую себя лучше, потому что знаю, что я не один! Размер 'fftBins' правильный - первый бин DC (ноль), тогда у вас есть первая половина симметричного набора бинов. Я не совсем уверен, почему результаты симметричны (как-то связано с тем, что это «настоящее» преобразование), но я знаю, что ячейки, которые вы получаете после БПФ, будут просто зеркально отражены. - person protectedmember; 10.06.2012
comment
См. полный пример, который вы запрашивали здесь. I думаю, что частотный спектр действительно содержит зеркало, и поэтому он должен быть той же длины, что и вход, что объясняет ваш сбой. - person cmbryan; 29.06.2012