Block convoluiton using skew transform (overlap-add method)
Contents
Overlap-add method
function []=overlapaddqdft_demo()
% Classic overlap-add method is using FFT size of 2N, where N is block size [1]. % Proposed method is using skew transform of size N for computation reduction [2]. % Convolution mod(x^N-j) is used for each block, and the skew transform is % an eigen transform of this skew convolution. % It is easy to see that multiplication of two polynomials y(z)=x(z)*h(z) (mod (x^N-j)), % where x(z)=x(0)+x(1)*z+x(2)*z^2+..+x(N-1)*z^(N-1) is an input signal, % and h(z)=h(0)+h(1)*z+h(2)*z^2+..+h(N-1)*z^(N-1) is impulse response of a filter, % will give result of block convolution % if output is read as Y=[Re(y(0))... Re(y(N-1)), Im(y(0))... Im(y(N-1))].
Init
N=32; % block size x=randn(1,5*N); % input signal h=randn(1,N); % filter impulse response % y=fftfilt(h,x); % true result
Classic overlap-add method (FFT size = 2*N)
hs=fft(h',2*N); % filter spectral response xn=reshape(x,N,[]); xn=[xn; zeros(size(xn))]; xs=fft(xn); % block spectrum of input signal (FFT size = 2*N) ys=bsxfun(@times,hs,xs); % spectral domain multiplication y1=real(ifft(ys)); % block convolution result y2=y1(1:N,:)+[zeros(N,1) y1((1:N)+N,1:end-1)]; % overlap-add block combination ycl=reshape(y2,[],1); % block-wise graph figure(2) plot_blockwise_classic(y1,N,length(x)) subplot(size(y1,2)+1,1,size(y1,2)+1); plot(ycl) axis([0 round(length(x)+N*1.1) -20 20]); grid on ylabel(['output']);
Proposed overlap-add method (FFT size = N)
w=exp(1i*pi/2/N*(0:N-1)'); % diagonal elements for qDFT hs=fft(w.*h'); xn=reshape(x,N,[]); x1=bsxfun(@times,w,xn); % pre-multiplication by diagonal twiddle factors s1=fft(x1); % block spectrum of input signal (qDFT size = N) s2=bsxfun(@times,hs,s1); % spectral domain multiplication y1=bsxfun(@times,conj(w),ifft(s2)); % inverse skew transform, block convolution result y2=real(y1)+[zeros(N,1) imag(y1(:,1:end-1))]; % overlap-add block combination (output is read as Y=[Re(y(0))... Re(y(N-1)), Im(y(0))... Im(y(N-1))]) ypr=reshape(y2,1,[]); % block-wise graph figure(1) % title('Proposed qDFT based method'); plot_blockwise_propose(y1,N,length(x)) % plot resulting output subplot(size(y1,2)+1,1,size(y1,2)+1); plot(ypr) axis([0 round(length(x)+N*1.1) -20 20]); grid on ylabel(['output']);
Compare results
figure(3) plot(ycl) hold on plot(ypr,'--r'); hold off grid on legend('classic','proposed')
References
[1] Blahut, R.E.: Fast Algorithms for Signal Processing. Cambridge University Press (2010). (p. 198)
[2] Jung Gap Kuk, Seyun Kim, and Nam Ik Cho, "A New Overlap Save Algorithm for Fast Block Convolution and Its Implementation Using FFT," Journal of Signal Processing Systems(Online), Feb 2010.
function []=plot_blockwise_classic(y1,N,lenx) for i=1:size(y1,2), y9=zeros(size(y1)); y9(:,i)=y1(:,i); y9=y9(1:N,:)+[zeros(N,1) y9((1:N)+N,1:end-1)]; y9=reshape(real(y9),1,[]); subplot(size(y1,2)+1,1,i); plot(y9) hold on a=17; plot([0 0]+(i-1)*N,[-a a],'r'); plot([0 0]+(i-1+2)*N,[-a a],'r'); text(1+(i-1)*N,-a*0.8,'fftsize=2N'); text(1+(i-1)*N,a*0.8,['real(Y' num2str(i) ')']); hold off axis([0 round(lenx+N*1.1) -20 20]); grid on ylabel(['block ' num2str(i)]); end function []=plot_blockwise_propose(y1,N,lenx) for i=1:size(y1,2), y9=zeros(size(y1)); y9(:,i)=y1(:,i); y9(:,2:end)=real(y9(:,2:end))+imag(y9(:,1:end-1)); y9=reshape(real(y9),1,[]); subplot(size(y1,2)+1,1,i); plot(y9) hold on a=17; plot([0 0]+(i-1)*N,[-a a],'r'); plot([0 0]+(i-1+1)*N,[-a a],'r'); plot([0 0]+(i-1+2)*N,[-a a],'r'); text(1+(i-1)*N,-a*0.8,'fftsize=N'); text(1+(i-1)*N,a*0.8,['real(Y' num2str(i) ')']); text(1+(i-1+1)*N,a*0.8,['imag(Y' num2str(i) ')']); hold off axis([0 round(lenx+N*1.1) -20 20]); grid on ylabel(['block ' num2str(i)]); end