DSPRelated.com
Code

Fast convolution

Hernán Ordiales November 9, 2010 Coded in Matlab

Fast convolution of an audio signal with the impulse response of a system modeled as LTI (Linear Time Invariant) one.

Uses FFT to perform the convolution by multiplication in the frequency domain. To reduce in this way, the computation time.

Works with mono or stereo input signals.

%
%   Copyright (C) 2004 by Hernán Ordiales
%   <audiocode@uint8.com.ar>
%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%

function fast_conv( file, impulse, output )
% Fast convolution of an audio signal with the impulse response of a system modeled as LTI (Linear Time Invariant) one.
% USE: fast_conv( 'source.wav', 'impulse_response.wav', 'output.wav' );

h_stereo = true;
x_stereo = true;

clip_factor = 1.01; % clip factor default value

% impulse response:
[ h, Fs1 ] = wavread( impulse ); % 2 columns matrix, one per channel
h1 = h(:,1); % col 1 -> left channel
h_channels = size(h); h_channels = h_channels(2);
if( h_channels == 2 )
	h2 = h(:,2); % col 2 -> right channel
else
	h2 = h(:,1); % col 1 -> left channel
	h_stereo = false;
end

% file to process:
[ x, Fs2 ] = wavread( file );
x1 = x(:,1); % col 1 -> left channel
x_channels = size(x); x_channels = x_channels(2);
if( x_channels == 2 )
	x2 = x(:,2); % col 2 -> right channel
else
	x2 = x(:,1); % col 1 -> left channel
	x_stereo = false;
end

% if sample rates are the same
if( Fs1 == Fs2 )

	% searches for the amount of points required to perform the FFT
	L = length(h1) + length(x1) - 1; % linear convolution length

	disp('Processing...');

	
	% Use nextpow if you have it to replace below code -> N = 2^nextpow(L);
	N = 2;
	while( N<L ) % first 2 pow greater than L
		N = N*2;
	end
	

	% Note: N>=L is needed because the IDFT of the multiplication is the circular convolution and to match it to the
	% common one, N>=L is required (where L=N1+N2-1;N1=length(x);N2=length(h))
	

	% FFT(X,N) is the N points FFT, with zero padding if X has less than N points and truncated if has more.
	H1 = fft( h1, N ); % Fourier transform of the impulse
	X1 = fft( x1, N ); % Fourier transform of the input signal
	
	F_y1 = H1 .* X1; % spectral multiplication

	y1 = ifft( F_y1 ); % time domain again

	% audio normalization: if "y = y/max(y)" -> "values out of [-1,+1] range are clipped"
	y1 = y1/( max(y1)*clip_factor ); % to avoid clipping

	% if one of the files is stereo, process the other channel
	if( h_stereo || x_stereo )
		H2 = fft( h2, N ); % Fourier transform of the impulse
		X2 = fft( x2, N ); % Fourier transform of the input signal

		F_y2 = H2 .* X2; % spectral multiplication
		y2 = ifft( F_y2 ); % time domain again

		y2 = y2/( max(y2)*clip_factor ); % to avoid clipping

		y = [ y1 y2 ]; % stereo output (two channels)
	else
		y = y1; % mono output
	end

	wavwrite( y, Fs1, output );

	disp( 'Convolution success.' );

else

	disp('Error: files has different sample rate.');

end