#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2006 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.
#
# Fast convolution of an audio signal with the impulse response of a system modeled as LTI (Linear Time Invariant) one.
# Use: fast_conv.py source.wav impulse_response.wav output.wav
from wav_array import *
from FFT import fft, inverse_fft
from pylab import size
import sys
def nextpow2( L ):
N = 2
while N < L: N = N * 2
return N
def fast_conv_vect( x, h ):
# searches for the amount of points required to perform the FFT
L = size(h) + size(x) - 1 # linear convolution length
N = nextpow2( L )
# 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.
H = fft( h, N ) # Fourier transform of the impulse
X = fft( x, N ) # Fourier transform of the input signal
Y = H * X # spectral multiplication
y = inverse_fft( Y ) # time domain again
return y
source = sys.argv[1]
impulse = sys.argv[2]
conv_output = sys.argv[3]
clip_factor = 1.01 # clip factor default value
[ h1, Fs1, h_bits ] = wavread( impulse ) # impulse response
[ x1, Fs2, x_bits ] = wavread( source ) # file to process
if Fs1 == Fs2 : # if sample rates are the same
print "Processing..."
y1 = fast_conv_vect( x1, h1 ).real # takes the real part to avoid a too small complex part (around e-18)
# audio normalization: if "y = y/max(y)" -> "values out of [-1,+1] range are clipped"
y1 = y1/( max(y1)*clip_factor ) # to avoid clipping
wavwrite( y1, Fs1, conv_output )
print "Output file:", conv_output
print "Convolution success."
else:
print "Error: files has different sample rate."
function xdft=fdft(x)
N=length(x);
xdft(1,N)=0; % defining a 1xN sequence with all the elements equals to zero.
%*************THIS IS THE DFT IMPLEMENTATION**************
%For each value of k, the Summatory function is computed over the interval 0<n<N-1.
for k=0:N-1,
for n=0:N-1,
xdft(k+1)=xdft(k+1) + x(n+1)*exp(-j*2*pi*k*n/N);
end
end
%NOTE: You may skip the use of for-loops by defining k and n as two N-points sequences. This is:
% k=0:N-1; n=0:N-1;
%The DFT is now computed in matrix form (as a matrix multiplication of the N-points Fourier Matrix and the discrete-time sequence x).
//Program to find and plot the frequency response of
//(1) Hanning window (2)Hamming window for M = 11
clear all;
close;
clc
M = 11;
for n = 1:M
h_hann_11(n) = 0.5-0.5*cos(2*%pi*(n-1)/(M-1));
h_hamm_11(n) = 0.54-0.46*cos(2*%pi*(n-1)/(M-1));
end
subplot(2,1,1)
[h_hann_11_M,fr]=frmag(h_hann_11,512);
h_hann_11_M = 20*log10(h_hann_11_M./max(h_hann_11_M));
plot2d(fr,h_hann_11_M,2);
title('Frequency Response 0f Hanning window Filter length M =11')
subplot(2,1,2)
[h_hamm_11_M,fr]=frmag(h_hamm_11,512);
h_hamm_11_M = 20*log10(h_hamm_11_M./max(h_hamm_11_M));
plot2d(fr,h_hamm_11_M,2);
title('Frequency Response of Hamming window Filter length M =11')
% David Valencia
% Posted @ DSPRelated.com
% in: http://www.dsprelated.com/showcode/10.php
function [y] = upsample2(x,N)
lx = length(x);
y = 0;
% Put first sample in the first position of the output
y(1) = x(1);
for i=2:lx
% Create a "chunk" (or piece) of vector, composed
% with a series of zeros and the next sample from
% the input
chunk = [zeros(1,N-1),x(i)];
% Append the chunk to the current output vector
y = [y,chunk];
end
%
% 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
% FFTRESAMPLE Resample a real signal by the ratio p/q
function y = fftResample(x,p,q)
% --- take FFT of signal ---
f = fft(x);
% --- resize in the FFT domain ---
% add/remove the highest frequency components such that len(f) = len2
len1 = length(f);
len2 = round(len1*p/q);
lby2 = 1+len1/2;
if len2 < len1
% remove some high frequency samples
d = len1-len2;
f = f(:);
f(floor(lby2-(d-1)/2:lby2+(d-1)/2)) = [];
elseif len2 > len1
% add some high frequency zero samples
d = len2-len1;
lby2 = floor(lby2);
f = f(:);
f = [f(1:lby2); zeros(d,1); f(lby2+1:end)];
end
% --- take the IFFT ---
% odd number of sample removal/addition may make the FFT of a real signal
% asymmetric and artificially introduce imaginary components - we take the
% real value of the IFFT to remove these, at the cost of not being able to
% reample complex signals
y = real(ifft(f));
function DemoProposed
% Author: J. Selva.
% First version: Sept. 2007.
%
% This m file contains the code for generating Fig. 2 in Sec. IV.A of paper
% "Convolution-based trigonometric interpolation of band-limited signals", IEEE
% Transactions on Signal Processing, vol. 56, n. 11, pp. 5465-5477, Nov. 2008. The
% equation numbers and references in this m file refer to this publication.
%
% Some comments:
%
% -The function 'KnabAPPeriodicApprox' computes the coefficients G(k/NT) in Sec. IV. This
% function takes several minutes, given that it involves a large number of numerical
% integrals which are performed in function KnabAPSpectrum. However, this must be done
% only once for fixed T, B, P and N, given that the G(k/NT) are independent of the sample
% values.
%
% 'RealTestSignal' implements a band-limited signal which consists of a sum of sinc pulses
% with arbitrary amplitudes and delays.
%
% 'FraserFFTUpsampling' implements the well-known zero-padding FFT
% algorithm. 'ProposedFFTUpsampling' implements the upsampling method in Sec. IV. It is
% worth comparing the code of both functions below.
warning off
T = 1; %Sampling period.
B = 0.5; %Two-sided bandwidth.
P = 18; %Pulse semi-length.
N = 1024; %Number of samples.
%Test signal composed of N+200 sinc pulses with random amplitudes and delays.
Sig = @(t)RealTestSignal(t,B,T,[-100,N+100],N+200);
%Compute coefficients Gn. This takes a while (5 minutes) because it is necessary to
%compute a large number of numerical integrals. However, since this step does not depend
%on the signal samples, it can be performed off-line and once ever.
disp(['Computing spectral coefficients. This takes a few minutes (7 or less), but ', ...
'must be done only',sprintf('\n'),'once ever for fixed T, B, P, and N.'])
% 'KnabAPPeriodicApprox' returns the frequency grid, specified by the first frequency fo
% and the frequency increment Df, the coefficients Gn, one for each grid frequency, and
% the truncation index kg.
[fo,Df,Gn,kg] = KnabAPPeriodicApprox(T,B,P,N);
sRef = Sig((0:N-1)*T); %Vector of signal samples with spacing T.
a = 10; %Oversampling factor.
sUpExact = Sig((0:a*N-1)*T/a); %Exact signal samples with oversampling a.
sUpFraser = FraserFFTUpsampling(sRef,a); %Interpolated samples using a zero-padded FFT.
sUpProposed = ProposedFFTUpsampling(sRef,T,B,12,a,Gn,kg); %Interpolated samples using
%the proposed method.
to = 0; %First instant in time grid.
Dt = T/a; %Grid time increment.
%Plot the interpolation error in dB for the zero-padding FFT method and for the proposed
%method.
plot(to+(0:a*N-1)*Dt,20*log10(abs([sUpExact - sUpFraser;sUpExact - sUpProposed])))
xlabel('Time t/T')
ylabel('Interpolation error (dB)')
annotation(gcf,'textarrow',[0.2911 0.2536],[0.8119 0.7429],...
'String',{'This is the zero-padding','FFT error'});
annotation(gcf,'arrow',[0.3321 0.06964],[0.4833 0.6333]);
annotation(gcf,'textarrow',[0.3446 0.2643],[0.419 0.3548],...
'String',{'This is the error of the','proposed FFT method. Note',...
'that the scale is in dB !!'});
warning on
%=====================================================================
%
% Conventional zero-padding FFT algorithm
function sUp = FraserFFTUpsampling(s,a)
N = length(s);
sF = a * fftshift(fft(s)); %Compute the FFT of the signal samples.
if mod(N,2) == 0 %Pad with zeros to obtain over-sampling factor a.
sF(end) = 0.5*sF(end);
sF = [zeros(1,N*(a-1)/2),sF,zeros(1,N*(a-1)/2)];
else
sF = [zeros(1,(N*(a-1)+1)/2),sF,zeros(1,(N*(a-1)-1)/2)];
end
sUp = ifft(ifftshift(sF)); %Compute the inverse FFT.
%=====================================================================
%
% Proposed FFT algorithm
function sUp = ProposedFFTUpsampling(s,T,B,P,a,Gn,kg)
N = length(s);
sF = fft(s); %Compute the FFT of the signal samples.
sF = sF(1+mod(-kg:kg,N)) .* Gn * (N*a); %Repeat some of the spectral samples periodically,
%and apply the window specified by the vector Gn.
sF = sF(:).';
if mod(N,2) == 0 %Pad with zeros to obtain over-sampling factor a.
sF = [zeros(1,N*a/2-kg),sF,zeros(1,N*a/2-kg-1)];
else
sF = [zeros(1,(N*a-2*kg-1)/2),sF,zeros(1,(N*a-2*kg-1)/2)];
end
sUp = ifft(ifftshift(sF)); %Compute the inverse FFT.
%=====================================================================
%
% Returns the spectral coefficients Gn and the frequency grid specification f0, Df, Gn.
function [f0,Df,Gn,n0] = KnabAPPeriodicApprox(T,B,P,N)
Df = 1/(N*T);
n0 = floor((1/T-B/2)/Df);
f0 = -Df*n0;
Bg = 2/T-B;
Gn = KnabAPSpectrum(f0+Df*(0:2*n0),B,Bg,(P+1/2)*T)/N;
%=====================================================================
%
% Auxiliary function that computes the spectral coefficients Gn.
function G = KnabAPSpectrum(f,B,Bg,TL)
% B: Two-sided signal bandwidth.
% Bg: Two-sided bandwidth of output pulse.
% Be: Two-sided bandwidth of fast-decay pulse.
% TL: Window's width between zeros in time domain.
%
% The two-sided bandwidth of the output pulse is Bg = B+2*Be.
Nf = numel(f);
G = zeros(size(f));
Be = (Bg-B)/2;
Ba = (Bg+B)/2;
Int = @(x)ConvWindow(x,Be,2*TL);
for k = 1:Nf
if f(k)-Ba/2 <= -Be/2 && Be/2 <= f(k)+Ba/2
G(k) = 1;
else
IInt = IntervalIntersection([-Be/2,Be/2],f(k)+[-Ba/2,Ba/2]);
if ~isempty(IInt)
G(k) = quad(Int,IInt(1),IInt(2),1e-16);
end
end
end
% Auxiliary function. It computes samples of the continuous convolution of a square pulse
% with the Kaiser window.
function W = ConvWindow(f,B,TL)
%Kaiser window.
%B: Two-sided window width.
%TL: Width between zeros in time domain.
W = zeros(size(f));
I = abs(f) < B/2;
W(I) = besseli(0,pi*B*(TL/2)*sqrt(1-(2*f(I)/B).^2))/(B*sinc(j*B*TL/2));
function [IInt,RelAInd,RelBInd] = IntervalIntersection(IA,IB)
if IA(2) < IB(1) || IB(2) < IA(1) %No overlap case.
IInt = [];
RelAInd = [];
RelBInd = [];
return
end
SwapIntervals = diff(IA) > diff(IB);
if SwapIntervals %Force IA to be the sorter interval.
Ipr = IA;
IA = IB;
IB = Ipr;
end
if IA(1) < IB(1)
IInt = [IB(1),IA(2)]; %There is intersection to the left.
RelAInd = IB(1)-IA(1);
RelBInd = 0;
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
return
end
if IA(2) <= IB(2)
IInt = IA; %IA lies inside IB.
RelAInd = 0;
RelBInd = IA(1)-IB(1);
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
return
end
IInt = [IA(1),IB(2)]; %There is intersection to the right.
RelAInd = 0;
RelBInd = IA(1)-IB(1);
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
%=====================================================================
%
% Computes samples of a signal formed by sincs with random amplitudes and delays.
function s = RealTestSignal(t,B,T,I,Np)
Sr = rand('seed');
rand('seed',0); %Always select the same random numbers in the sequel.
M = numel(t);
Ap = (rand(Np,1)-0.5)*2 ; %Random amplitudes.
tp = I(1)+rand(Np,1)*diff(I); %Random delays.
rand('seed',Sr)
st = size(t);
t = t(:);
s = zeros(numel(t),1);
for r = 1:Np
s = s + sinc(B*(t-tp(r)))*Ap(r); %Compute sum of sincs
end
s = reshape(s,st);
//Continuous Time Fourier Series Spectral Coefficients of
//a periodic Cosine signal x(t) = cos(Wot)
clear;
close;
clc;
t = 0:0.01:1;
T = 1;
Wo = 2*%pi/T;
xt = cos(Wo*t);
for k =0:5
C(k+1,:) = exp(-sqrt(-1)*Wo*t.*k);
a(k+1) = xt*C(k+1,:)'/length(t); //fourier series is done
if(abs(a(k+1))<=0.01)
a(k+1)=0;
end
end
a =a';
ak = [a($:-1:1),a(2:$)];
disp(ak,'Continuous Time Fourier Series Coefficients are:')
//Result
//Continuous Time Fourier Series Coefficients are:
// column 1 to 11
// 0 0 0 0 0.5049505+1.010D-18i 0 0.5049505-1.010D-18i 0 0 0 0
function [y,X,H] = conv2d2(x,h)
[x1,x2] = size(x);
[h1,h2] = size(h);
X = zeros(x1+h1-1,x2+h2-1);
H = zeros(x1+h1-1,x2+h2-1);
Y = zeros(x1+h1-1,x2+h2-1);
for i = 1:x1
for j = 1:x2
X(i,j)=x(i,j);
end
end
for i =1:h1
for j = 1:h2
H(i,j)=h(i,j);
end
end
disp(X,'x=')
disp(H,'h =')
Y = fft2d(X).*fft2d(H);
disp(Y)
y = ifft2d(Y);
endfunction
/////////////////////////////////////////////
function [a2] = fft2d(a)
//a = any real or complex 2D matrix
//a2 = 2D-DFT of 2D matrix 'a'
m=size(a,1)
n=size(a,2)
// fourier transform along the rows
for i=1:n
a1(:,i)=exp(-2*%i*%pi*(0:m-1)'.*.(0:m-1)/m)*a(:,i)
end
// fourier transform along the columns
for j=1:m
a2temp=exp(-2*%i*%pi*(0:n-1)'.*.(0:n-1)/n)*(a1(j,:)).'
a2(j,:)=a2temp.'
end
for i = 1:m
for j = 1:n
if((abs(real(a2(i,j)))<0.0001)&(abs(imag(a2(i,j)))<0.0001))
a2(i,j)=0;
elseif(abs(real(a2(i,j)))<0.0001)
a2(i,j)= 0+%i*imag(a2(i,j));
elseif(abs(imag(a2(i,j)))<0.0001)
a2(i,j)= real(a2(i,j))+0;
end
end
end
/////////////////////////////////////////////////
function [a] =ifft2d(a2)
//a2 = 2D-DFT of any real or complex 2D matrix
//a = 2D-IDFT of a2
m=size(a2,1)
n=size(a2,2)
//Inverse Fourier transform along the rows
for i=1:n
a1(:,i)=exp(2*%i*%pi*(0:m-1)'.*.(0:m-1)/m)*a2(:,i)
end
//Inverse fourier transform along the columns
for j=1:m
atemp=exp(2*%i*%pi*(0:n-1)'.*.(0:n-1)/n)*(a1(j,:)).'
a(j,:)=atemp.'
end
a = a/(m*n)
a = real(a)
endfunction
// Random number generator that sounds pleasant in audio algorithms.
// The argument and return value is a 30-bit (positive nonzero) integer.
// This is Duttaro's 30-bit pseudorandom number generator, p.124 J.AES, vol 50 no 3 March 2002;
// I found this 30-bit pseudorandom number generator sounds far superior to the 31-bit
// pseudorandom number generator presented in the same article.
// To make result a signed fixed-point value, do not shift left into the sign bit;
// instead, subtract 0x20000000 then multiply by a scale factor.
#define NextRand(rr) (((((rr >> 16) ^ (rr >> 15) ^ (rr >> 1) ^ rr) & 1) << 29) | (rr >> 1))
//Program for Linear Convolution
clc;
clear all;
close ;
x = input('enter x seq');
h = input('enter h seq');
m = length(x);
n = length(h);
//Method : Using Direct Convolution Sum Formula
for i = 1:n+m-1
conv_sum = 0;
for j = 1:i
if (((i-j+1) <= n)&(j <= m))
conv_sum = conv_sum + x(j)*h(i-j+1);
end;
y(i) = conv_sum;
end;
end;
disp(y,'y=')
//Autocorrelation of a given Input Sequence
//Finding out the period of the signal using autocorrelation technique
clear;
clc;
close;
x = input('Enter the given discrete time sequence');
L = length(x);
h = zeros(1,L);
for i = 1:L
h(L-i+1) = x(i);
end
N = 2*L-1;
Rxx = zeros(1,N);
for i = L+1:N
h(i) = 0;
end
for i = L+1:N
x(i) = 0;
end
for n = 1:N
for k = 1:N
if(n >= k)
Rxx(n) = Rxx(n)+x(n-k+1)*h(k);
end
end
end
disp('Auto Correlation Result is')
Rxx
disp('Center Value is the Maximum of autocorrelation result')
[m,n] = max(Rxx)
disp('Period of the given signal using Auto Correlation Sequence')
n