0
$\begingroup$

I'm trying to make an FFT audio filter using overlap-add but there's some slight rhythmic distortion/crackle in the output. I have an irSize (impulse response size) of 512 samples and a blockSize of 512. The overlap is 512 samples. Since fftSize >= blockSize + irSize - 1, fftSize is 1024 samples. I'm using FFTS for the FFT so the output size of forward_real (fftBlockSize) is 1026.

Here are my steps:

// copy input
for(i = 0; i < blockSize; i++)
    fftBuffer[i] = inBuffer[i];

// set rest to zero
for(i = blockSize; i < fftBlockSize; i++)
    fftBuffer[i] = 0;

FFT::forward_real(fftSize, fftBuffer, fftBuffer);

// complex multiplication
for(i = 0; i < irSize + 1; i++)
{
    convBuffer[i * 2] = fftBuffer[i * 2] * irBuffer[i * 2] - fftBuffer[i * 2 + 1] * irBuffer[i * 2 + 1];
    convBuffer[i * 2 + 1] = fftBuffer[i * 2] * irBuffer[i * 2 + 1] + fftBuffer[i * 2 + 1] * irBuffer[i * 2];
}

FFT::inverse_real(fftSize, convBuffer, fftBuffer);

// overlap-add
for(i = 0; i < blockSize; ++i){
    outBuffer[i] = fftBuffer[i] + parts[i];
    parts[i] = fftBuffer[i + blockSize];
}

Here you can see the little jump in the output every 512 samples. This is the source of the distortion.

enter image description here

Any ideas? I've been struggling with this for days. It seems like either I'm doing the complex multiply or the overlap add slightly wrong. But I can't for the life of me figure it out. It seems like I'm doing the theory right.

Thanks.

$\endgroup$
  • $\begingroup$ Is irSize=512? If convBuffer only has 512 elements, then you would have a problem. $\endgroup$ – JRE May 21 '15 at 12:02
  • $\begingroup$ Thanks for the reply. No, convBuffer has 1026 elements. I'm fairly sure the problem isn't from a bad memory read. It's the algorithm that has problems. $\endgroup$ – Robert Clouth May 21 '15 at 12:20
1
$\begingroup$

For FFT fast convolution, the complex multiplication in the frequency domain needs to be done over the full length of the FFT (fftSize), not just the length of the impulse response in the time domain. Otherwise (for strictly real data and a strictly real impulse response) the IFFT input will likely no longer be conjugate symmetric.

$\endgroup$
  • $\begingroup$ Hi. The complex multiplication is done over the full FFT length. convBuffer is 1026 samples long (ordered real, imag, real, imag...) and while i in the for loop goes to 513, it is multiplied by 2. If the loop were to go higher than 513 it would try to access beyond the end of the arrays. Do you mean the full redundant symmetric part too? $\endgroup$ – Robert Clouth May 22 '15 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.