1
votes

I know that ifft sums multiple sine waves up from data obtain from doing an fft on a signal. is there a way to do a ifft using square waves instead of sine waves?
I'm not trying to get the original signal back but trying to rebuild it using square waves from the data taken from the fft instead of the normal sine wave summation process.

See simple example below: the signals I will be using are human audio signals about 60 seconds long so I'm trying to see if I can use / alter the ifft command in some way.

PS: I'm using Octave 4.0 which is similar to Matlab

clear all,clf reset, clc,tic
Fs = 200; % Sampling frequency
t=linspace(0,1,Fs);
freq=2;

%1 create signal
ya = .5*sin(freq*pi*2*t+pi); 

%2 create frequency domain
ya_fft = fft(ya);

%3 rebuild signal
mag = abs(ya_fft);
phase = unwrap(angle(ya_fft));
ya_newifft=ifft(mag.*exp(i*phase));
ifft_sig_combined_L1=ifft(mag.*exp(i*phase),Fs); %use Fs to get correct file length

% square wave
vertoffset=0.5;
A=1
T = 1/freq; % period of the signal
square = mod(t * A / T, A) > A / 2;
square = square - vertoffset;

subplot(3,1,1);
plot(t,ya,'r')
title('orignal signal')

subplot(3,1,2);
plot(t,ifft_sig_combined_L1)
title('rebuilt signal')

subplot(3,1,3);
plot(t,square)
title('rebuilt signal with square wave')

Image

1

1 Answers

1
votes

Define the basis vectors you want to use and let them be the columns of a matrix, A. If b is your signal, then just get the least squares solution to Ax = b. If A is full rank, then you will be able to represent b exactly.

Edit:

Think about what a matrix-vector product does: Each column of the matrix is multiplied by the corresponding element of the vector (i.e., the n^th column of the matrix is multiplied by the n^th element of the vector) and the resulting products are summed together. (This would be a lot easier to illustrate if this site supported latex.) In Matlab, a horrible but hopefully illustrative way to do this is

A = some_NxN_matrix;
x = some_Nx1_vector;
b = zeros( size(A,1), 1 );
for n = 1 : length(x)
  b = b + A(:,n) * x(n);
end

(Of course, you would never actually do the above but rather b = A*x;.)

Now define whatever square waves you want to use and assign each to its own Nx1 vector. Call these vectors s_1, s_2, ..., s_M, where M is the number of square waves you are using. Now let

A = [s1, s2, ..., s_M];

According to your question, you want to represent your signal as a weighted sum of these square waves. (Note that this is exactly what a DFT does it just uses orthogonal sinusoids rather than square waves.) To weight and sum these square waves, all you have to do is find the matrix-vector product A*x, where x is the vector of coefficients that weight each column (see the above paragraph). Now, if your signal is b and you want to the find the x that will best sum the square waves in order to approximate b, then all you have to do is solve A*x=b. In Matlab, this is given by

x = A \ b;

The rest is just linear algebra. If a left-inverse of A exists (i.e., if A has dimensions M x N and rank N, with M > N), then (A^-1) * A is an identity matrix and

(A^-1) * A * x = (A^-1) * b,

which implies that x = (A^-1) * b, which is what x = A \ b; will return in Matlab. If A has dimensions M x N and rank M, with N > M, then the system is underdetermined and a left-inverse does not exist. In this case you have to use the psuedo-inverse to solve the system. Now suppose that A is NxN with rank N, so that both the left- and right-inverse exist. In this case, x will give an exact representation of b:

x = (A^-1) * b
A * x = A * (A^-1) * b = b

If you want an example of A that uses square waves to get an exact representation of the input signal, check out the Haar transform. There is a function available here.