Em quase todos os casos, sua melhor opção não é a convolução nem a FFT, mas simplesmente a aplicação direta do filtro IIR (usando, por exemplo, a função sosfilt ()). Isso será muito mais eficiente em termos de CPU e consumo de memória.
A diferença numérica depende do filtro específico. O único caso em que alguma diferença pode surgir é se os pólos estiverem muito, muito próximos do círculo unitário. Mesmo existem alguns truques que podem ajudar. NÃO USE representação de função de transferência e filtro (), mas use pólos e zeros com sosfilt (). Aqui está um exemplo para a diferença.
n = 2^16; % filter length
fs = 44100; % sample rate
x = zeros(n,1); x(1) = 1;
f0 = 15; % cutoff frequency in Hz
% design with poles and zeroes
[z,p,k] = butter(5,f0*2/fs);
clf
plot(sosfilt(zp2sos(z,p,k),x));
% design with transfer function
[b,a] = butter(5,f0*2/fs);
hold on
plot(filter(b,a,x),'k');
filter () fica ruim com um ponto de corte de cerca de 15Hz a 44,1kHz. Para sosfilt (), o ponto de corte pode ficar bem abaixo de 1/100 de Hz a 44,1kHz, sem problemas.
Se você tiver problemas de estabilidade, a FFT também não ajuda muito. Como o filtro é IIR, a resposta ao impulso é infinita e precisa ser truncada primeiro. Nessas frequências muito baixas, a resposta ao impulso é tão longa que a FFT também se torna impraticável.
Por exemplo, se você deseja um corte de 1/100 Hz a 44,1 kHz e deseja uma faixa dinâmica na resposta ao impulso de 100 dB, precisará de aproximadamente 25 milhões de amostras !!! São quase 10 minutos a 44,1 kHz e muitas, muitas vezes mais que o sinal original