Question about overlap-add @Jim Clay: No if the filter varies slowly, then the clicks go away. So I guess the filter needs to vary slowly to avoid audible clicking sounds.

I created a test in matlab where I'm comparing time-domain filtering with frequency-domain filtering. The two operations produce the same output, but I get clicks in the audio when I switch filter parameters periodically. How do I solve that?

Here's my script:

clc
close all
clear all

[x,fs] = wavread('audiosignal');
x = x';
numberOfFilterTaps = 256;
NFFT = numberOfFilterTaps * 2;
z1 = zeros(1,numberOfFilterTaps-1);
blockSize = 64;
numberOfSamples = length(x);
h1 = fir1(numberOfFilterTaps-1, 0.5);
h2 = fir1(numberOfFilterTaps-1, 0.9);
blockCounter = 0;
ola = zeros(1,NFFT);
enableThis = 1;
switchCounter = 0;

while 1
    idx1 = 1 + blockSize * blockCounter;
    idx2 = blockSize + blockSize * blockCounter;

    if (idx2 &gt; numberOfSamples)
        break;
    end

    idx = idx1:idx2;

    sampleBlock = x(idx);

    % Switch filter periodically
    if (switchCounter == 0)
        switchCounter = 0;
        if (enableThis)
            h = h1;
            H = fft(h,NFFT);
            enableThis = 0;
        else
            enableThis = 1;
            h = h2;
            H = fft(h,NFFT);
        end
    end
    switchCounter = switchCounter +1;
    if (switchCounter &gt; 60)
        switchCounter = 0;
    end

    % Method #1
    [y1(idx),z1] = filter(h,1,sampleBlock,z1);

    % Method #2
    tmp = real(ifft(fft(sampleBlock, NFFT) .* H));
    tmp = tmp + ola;
    ola = [tmp(blockSize+1:end) zeros(1,blockSize)];
    y2(idx) = tmp(1:blockSize);

    blockCounter = blockCounter + 1;
end

wavwrite(y1,fs,'output_y1');
wavwrite(y2,fs,'output_y2');
The main issue here is that you are implementing a time-variant filter. Both FIR filter and overlap algorithms are only valid if your filter is time-invariant.

If you need time variant filters, you need to solve two problems: continuity of the state variable and continuity of the output waveform. The easiest way to deal with this is to basically run both filters in parallel and then cross-fade between the outputs at switch time. The time constant of the cross fade determines what audibility you get, so this can be adjusted to the desired level.