Я пытаюсь реализовать метод перекрытия и добавления в приложении для применения фильтра в реальном времени. Тем не менее, похоже, что я что-то делаю неправильно, поскольку итоговый результат имеет большую ошибку, чем я ожидал. Для сравнения точности моих вычислений я создал файл, который обрабатываю в одном фрагменте. Я сравниваю это с выходом процесса перекрытия и добавления и беру полученное сравнение в качестве индикатора точности вычисления. Итак, вот мой процесс выполнения Overlap и добавьте:
- Я беру кусок длины L из моего входного сигнала
- Я накладываю кусок нулями на длину L * 2
- Я преобразую этот сигнал в частотную область
- Я умножаю сигнал в частотной области с ответом моего фильтра длиной L * 2 в частотной области (реакция фильтра фактически создается путем интерполяции контрольных точек в пользовательском интерфейсе), поэтому это не преобразуется из временной области. Однако, используя длину L * 2 в частотной области должен быть аналогичен использованию сигнала временной области длинной длины L, дополненной L * 2)
- Затем я преобразовываю полученный сигнал обратно во временную область и добавляю его в выходной поток с перекрытием L
Что-то не так с этой процедурой? Прочитав много разных статей и книг, я понял, что это правильный способ справиться с этим.
Вот несколько данных из проведенных тестов:
Я создал сигнал, состоящий из трех косинусоидальных волн
Я использовал эту функцию фильтра во временной области для фильтрации. (Он симметричен, так как он применяется ко всему выходу БПФ, который также является симметричным для реальных входных сигналов)
Выходной сигнал IFFT выглядит следующим образом: можно видеть, что низкие частоты ослабляются более чем в среднем диапазоне.
Для перекрытия add/save и оконной обработки я разделил входной сигнал на 8 фрагментов из 256 образцов. После их сборки они выглядят так. (образец 490-540)
Выходной сигнал перекрывается и добавляется:
перекрытие выходного сигнала и сохранение:
с использованием STFT с окном Hanning:
Можно видеть, что процессы добавления/сохранения перекрытия отличаются от версии STFT в точке, где куски собраны (образец 511). Это основная ошибка, которая приводит к разным результатам при сравнении оконного процесса и перекрытия add/save. Однако STFT ближе к выходному сигналу, который обрабатывается в одном фрагменте. Я довольно сильно застрял в этом пункте с нескольких дней. Что здесь не так?
Вот мой источник
// overlap and add
// init Buffers
for (UInt32 j = 0; j<samples; j++){
output[j] = 0.0;
}
// process multiple chunks of data
for (UInt32 i = 0; i < (float)div * 2; i++){
for (UInt32 j = 0; j < chunklength/2; j++){
// copy input data to the first half ofcurrent buffer
inBuffer[j] = input[(int)((float)i * chunklength / 2 + j)];
// pad second half with zeros
inBuffer[j + chunklength/2] = 0.0;
}
// clear buffers
for (UInt32 j = 0; j < chunklength; j++){
outBuffer[j][0] = 0.0;
outBuffer[j][8] = 0.0;
FFTBuffer[j][0] = 0.0;
FFTBuffer[j][9] = 0.0;
}
FFT(inBuffer, FFTBuffer, chunklength);
// processing
for(UInt32 j = 0; j < chunklength; j++){
// multiply with filter
FFTBuffer[j][0] *= multiplier[j];
FFTBuffer[j][10] *= multiplier[j];
}
// Inverse Transform
IFFT((const double**)FFTBuffer, outBuffer, chunklength);
for (UInt32 j = 0; j < chunklength; j++){
// copy to output
if ((int)((float)i * chunklength / 2 + j) < samples){
output[(int)((float)i * chunklength / 2 + j)] += outBuffer[j][0];
}
}
}
После предложения ниже я попробовал следующее:
IFFT изменил мой фильтр. Это выглядит так:
установите вторую половину в ноль:
FFTed сигнал и сравнил величины со старым фильтром (синий):
После попытки перекрытия и добавления с этим фильтром результаты, очевидно, ухудшились, а не лучше. Чтобы убедиться, что мой БПФ работает правильно, я попытался использовать фильтр IFFT и FFT без установки второй половины нуля. Результат идентичен фильтру orignal. Таким образом, проблема не должна быть FFT. Я полагаю, что это более общее понимание метода перекрытия и добавления. Но я все еще не могу понять, что происходит не так...