Я пытаюсь реализовать перекрытие и добавить метод, чтобы применить фильтр в контексте реального времени. Однако мне кажется, что я что-то делаю неправильно, так как полученный результат содержит большую ошибку, чем я ожидал. Для сравнения точности вычислений я создал файл, который обрабатываю одним фрагментом. Я сравниваю это с выходом процесса перекрытия и добавления и беру полученное сравнение как индикатор точности вычислений. Итак, вот мой процесс выполнения Overlap и добавления:
Что-то не так с этой процедурой? Прочитав много разных статей и книг, я стал неуверен, как правильно с этим справиться.
Я использовал эту функцию фильтрации во временной области для фильтрации. (Он симметричен, поскольку применяется ко всему выходу БПФ, что также является симметричным для реальных входных сигналов)
Выходные данные IFFT выглядят следующим образом: можно видеть, что низкие частоты ослабляются больше, чем частота в среднем диапазоне.
Для добавления / сохранения с перекрытием и оконной обработки я разделил входной сигнал на 8 блоков по 256 отсчетов. После сборки они выглядят так. (образцы 490–540)
Выходной сигнал перекрывается и добавляет:
выходной сигнал перекрывается и сохраняется:
выходной сигнал с использованием STFT с окном Хэннинга:
Можно видеть, что перекрывающиеся процессы добавления / сохранения отличаются от версии STFT в том месте, где фрагменты объединяются (пример 511). Это основная ошибка, которая приводит к разным результатам при сравнении оконного процесса и перекрытия добавления / сохранения. Однако 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 обработал мой фильтр. Это выглядит так:
обнуляет вторую половину:
Произвели БПФ сигнала и сравнили величины со старым фильтром (синий):
После попытки сделать перекрытие и сложение с помощью этого фильтра результаты явно стали хуже, а не лучше. Чтобы убедиться, что мой БПФ работает правильно, я попытался выполнить ОБПФ и БПФ фильтра, не устанавливая вторую половину нуля. Результат идентичен оригинальному фильтру. Так что проблема не в БПФ. Я полагаю, что это скорее общее понимание метода перекрытия и добавления. Но я все еще не могу понять, что не так ...