Вы находитесь на странице: 1из 23

Elec 484

Assignment 5

Matthew Pierce

V00126204
Part 1
Convolve two sequences (vectors) of 32 numbers in several ways as described below,
both in time and frequency domain, and check to see if both give the same result. Repeat
by convolving two sound files 3-5 seconds long each (frequency domain only, no need to
compare with time domain). For the first sound file use the flute signal, for the second
sound file, use a drum signal.

Explain which method(s) is/are correct, and what is wrong with the other methods.
Provide the Matlab code, numerical results for short vectors, and copies of the input and
output wav files in each case.

a. Circular (cyclic, periodic) convolution in frequency domain (entire file length).


Result will be same length as input.

The following Matlab program computes the circular convolution of two signals (x and
h) in the time domain (the software is also available on the website):

% Cyclic convolution in the time domain


function y = cyc_convolve_time(x, h)

% Make the filter (h) an even length (for indexing)


if(mod(length(h), 2)>0)
h(length(h)+1) = 0;
end

% Set the N value


N = length(h);

% Initialize the output vector


y = zeros(1, length(x));

for n=1:N:length(x)

if(n+N>length(x))
% Account for the last segment
x_i = x(n:length(x)-1);
else
% Partition the signal into size N
x_i = x(n:n+N-1);
end

% Find the convolution for this segment over two cycles of h


y_temp = convn(x_i, [h h], 'same');

% Get the length of this output segment


if(mod(length(y_temp), 2)>0)
y_temp(length(y_temp)+1) = 0;
end
len = length(y_temp);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+len/2-1) = y(n:n+len/2-1) + y_temp(1:len/2);
elseif(n==1)
y(n:n+len-1) = y_temp;
continue;
end

% Add the "new" values to the output


y(n+len/2:n+len-1) = y_temp(len/2+1:len);

end

% Plot this convolution


plot(y);
title('Cyclic Convolution: Time Domain'), xlabel('Time'), ylabel('Convolved Signals');

end

Another, similar program, used to compute the circular convolution of two signals in the
frequency domain (using FFT filtering) is given below (again, also available on the
website):

% Cyclic convolution in the frequency domain using FFT filtering


function y = cyc_convolve_freq(x, h)

% Make the filter (h) an even length (for indexing)


if(mod(length(h), 2)>0)
h(length(h)+1) = 0;
end

% Set the N value


N = length(h);

% Take the filter fft


H = fft(h);

% Initialize the output vector


y = zeros(1, length(x));

for n=1:N:length(x)
if(n+N>length(x))
% If the segment is shorter than h, only take the n point fft
H = fft(h, length(x)-n);
x_i = x(n:length(x)-1);
else
% Partition the signal into size N
x_i = x(n:n+N-1);
end

% Take the fft of this segment


X_i = fft(x_i);

% Find the frequency domain product for this segment


Y_i = X_i.*H;

% Find the inverse fft to get the convolution for this segment
y_temp = ifft(Y_i);
if(mod(length(y_temp), 2)>0)
y_temp(length(y_temp)+1) = 0;
end
len = length(y_temp);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+len/2-1) = y(n:n+len/2-1) + y_temp(1:len/2);
elseif(n==1)
y(n:n+len-1) = y_temp;
continue;
end

% Add the "new" values to the output


y(n+len/2:n+len-1) = y_temp(len/2+1:len);

end

% Plot this convolution


plot(y);
title('Cyclic Convolution: Frequency Domain'), xlabel('Time'), ylabel('Convolved
Signals');

end

Process:
First, I tested the two programs using two numerical vectors of length 32 with the
following values:
x = linspace(0, 1, 32);
h = linspace(1, 0, 32);

Using the plots produced by each program, we can see that the results are the same:

Cyclic convolution in the time domain


Cyclic convolution in the frequency domain

Following this, I read two audio files into the x and h vectors (both original audio files
are available on the website):

x = wavread(flute2.wav);
h = wavread(short_beat.wav);

Using just the frequency domain convolution program, I convolved the two signals
together to produce a signal that could be written to an output audio file using the
following commands:

y = cyc_convolve_freq(x, h);
wavwrite(y, 44100, 16, cyc_conv_freq.wav);

The output file cyc_conv_freq.wav is available on the website to listen to.

b. Acyclic (aperiodic) convolution in frequency domain using zero padding (entire


file length) (result will be twice the original file length)
The following Matlab program computes the acyclic convolution of two signals (x and h)
in the time domain (the software is also available on the website):

% Acyclic convolution in the time domain


function y = acyc_convolve_time(x, h)

% Set the N value


N = length(h);

% Initialize the filter and zero pad


h = [h, zeros(1, N)]; % This signal is length 2N

% Initialize the output vector


y = zeros(1, length(x)*2-1);

for n=1:N:length(x)

if(n+N>length(x))
% If the segment is shorter than h find the proper length
x_i = [x(n:length(x)-1), zeros(1, (n+N)-length(x)), zeros(1, N)];
else
% Partition the signal into size N and zero pad
x_i = [x(n:n+N-1), zeros(1, N)];
end

% Find the convolution for this segment


y_temp = conv(x_i, h);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+N-1) = y(n:n+N-1) + y_temp(1:N);
elseif(n==1)
y(n:n+2*N-1) = y_temp(1:length(x)*2);
continue;
end

% Add the "new" values to the output


y(n+N:n+2*N-1) = y_temp(N+1:N*2);

end

plot(y);
title('Acyclic Convolution: Time Domain'), xlabel('Time'), ylabel('Convolved Signals');

end
Another, similar program, used to compute the acyclic convolution of two signals in the
frequency domain (using FFT filtering) is given below (again, also available on the
website):

% Acyclic convolution in the frequency domain using FFT filtering


function y = acyc_convolve_freq(x, h)

% Set the N value


N = length(h);

% Initialize the filter, zero pad, and take its fft


h = [h, zeros(1, N)]; % This signal is length 2N
H = fft(h);

% Initialize the output vector


y = zeros(1, length(x)*2-1);

for n=1:N:length(x)

if(n+N>length(x))
% If the segment is shorter than h find the proper length
x_i = [x(n:length(x)-1), zeros(1, (n+N)-length(x)), zeros(1, N)];
else
% Partition the signal into size N and zero pad
x_i = [x(n:n+N-1), zeros(1, N)];
end

% Partition the signal into size N, zero pad, and take its fft
X_i = fft(x_i);

% Find the frequency domain product for this segment


Y_i = X_i.*H;

% Find the inverse fft to get the convolution for this segment
y_temp = ifft(Y_i);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+N-1) = y(n:n+N-1) + y_temp(1:N);
elseif(n==1)
y(n:n+N*2-1) = y_temp;
continue;
end

% Add the "new" values to the output


y(n+N:n+N*2-1) = y_temp(N+1:N*2);

end

plot(y);
title('Acyclic Convolution: Frequency Domain'), xlabel('Time'), ylabel('Convolved
Signals');

end

Process:
First, I tested the two programs using two numerical vectors of length 32 with the
following values:

x = linspace(0, 1, 32);
h = linspace(1, 0, 32);

Using the plots produced by each program, we can see that the results are the same:

Acyclic convolution in the time domain


Acyclic convolution in the frequency domain

Following this, I read two audio files into the x and h vectors (both original audio files
are available on the website):

x = wavread(flute2.wav);
h = wavread(short_beat.wav);

Using just the frequency domain convolution program, I convolved the two signals
together to produce a signal that could be written to an output audio file using the
following commands:

y = acyc_convolve_freq(x, h);
wavwrite(y, 44100, 16, acyc_conv_freq.wav);

The output file acyc_conv_freq.wav is available on the website to listen to.

c. Circular (cyclic, periodic) convolution on windowed overlapping segments,


raised cosine windows, cyclic shift, and overlap-add (DAFX figure 8.5 where
the time-frequency processing is a multiplication with the time/frequency
coefficients of a second signal, keep the phases of only one of the signals). See
also figure 8.28. Use windows 8 samples long for numbers, 2048 samples long
for audio file

The following Matlab program computes the circular convolution of two signals (x and
h) using windowed overlapping segments, raised cosine windows, cyclic shift, and
overlap-add (the software is also available on the website):

% Cyclic convolution using overlapping raised cosine windows


function y = cyc_rcos_window_conv(x, h, N)

% Create the raised cosine function


rcos_win = 1/2*(1-cos(2*pi*(1:N)/N));

% Initialize output signal


y = zeros(1, length(x));

for n=1:N:length(x)

if(n+N>=length(x))
% Account for shorter segment (last one)
x_i = x(n:length(x));
h_i = h(n:length(x));
H_i = fft(h_i);
rcos_win = 1/2*(1-cos(2*pi*(1:length(x)-n+1)/(length(x)-n+1)));
else
% Partition the signals into size N
x_i = x(n:n+N-1);
h_i = h(n:n+N-1);
% Take the fft of the filter to get time-freq coefficients
H_i = fft(h_i);
end

% Piecewise multiply the input segment with the cosine function


x_rcos = x_i .* rcos_win;

% Perform a circular shift on the time domain segment


x_rcos_shft = circshift(x_rcos, [0, N/2]);

% Take the fft of the windowed input


X_rcos_shft = fft(x_rcos_shft);

% Multiply this windowed segment fft with the filter fft


Y_rcos_shft = X_rcos_shft .* abs(H_i); % Only take first phase

% Find the time domain output (still shifted) using ifft


y_rcos_shft = ifft(Y_rcos_shft);

% "Unshift" the segment


y_rcos = circshift(y_rcos_shft, [0, N/2]);

% Make the segment an even length


if(mod(length(y_rcos), 2)>0)
y_rcos(length(y_rcos)+1) = 0;
end

% Get the length value


len = length(y_rcos);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+len/2-1) = y(n:n+len/2-1) + y_rcos(1:len/2);
elseif(n==1)
y(n:n+len-1) = y_rcos;
continue;
end

% Add the "new" values to the output


y(n+len/2:n+len-1) = y_rcos(len/2+1:len);

end

% Plot the convolution


plot(y);
title('Cyclic Convolution: Raised Cosine Windows'), xlabel('Time'), ylabel('Convolved
Signals');

end

Process:
First, I tested the program using two numerical vectors of length 32 with the following
values:

x = rand(1, 32);
h = linspace(0, 1, 32);

and a window size (N value) of 8. Using the plot produced by the program, we can see
the results:
Cyclic convolution using raised cosine windowing

Following this, I read two audio files into the x and h vectors (both original audio files
are available on the website):

x = wavread(flute2.wav);
h = wavread(short_beat.wav);

Using the convolution program with a window size of 2048, I convolved the two signals
together to produce a signal that could be written to an output audio file using the
following commands:

y = cyc_rcos_window_conv(x, h, 2048);
wavwrite(y, 44100, 16, cyc_rcos_win_conv.wav);

The output file cyc_rcos_win_conv.wav is available on the website to listen to.

d. Acyclic (aperiodic) convolution in frequency domain using zero padding using


rectangular windows (DAFX figure 8.20) and overlap-add. 8 samples long for
numbers, 2048 samples long for audio file.
The following Matlab program computes the acyclic convolution of two signals (x and h)
using rectangular windowing with a given window size (N) and overlap add (the software
is also available on the website):

% Acyclic convolution in the frequency domain using FFT filtering and rectangular
windowing of size N
function y = acyc_win_conv(x, h, N)

% Initialize the filter, zero pad, and take its fft


h = [h, zeros(1, N)]; % This signal is length 2N

% Initialize the output vector


y = zeros(1, length(x)*2-1);

for n=1:N:length(x)

if(n+N>length(x))
% If the segment is shorter than N find the proper length
x_i = [x(n:length(x)-1), zeros(1, (n+N)-length(x)), zeros(1, N)];
else
% Partition the signal into size N and zero pad
x_i = [x(n:n+N-1), zeros(1, N)];
end

% Take the 2N point fft of the filter


H = fft(h, 2*N);

% Take the fft of this segment


X_i = fft(x_i);

% Find the frequency domain product for this segment


Y_i = X_i.*abs(H);

% Find the inverse fft to get the convolution for this segment
y_temp = ifft(Y_i);

% Overlap add the first half of the output (after first pass)
if(n>1)
y(n:n+N-1) = y(n:n+N-1) + y_temp(1:N);
elseif(n==1)
y(n:n+N*2-1) = y_temp;
continue;
end

% Add the "new" values to the output


y(n+N:n+N*2-1) = y_temp(N+1:N*2);

end

% Plot the convolution


plot(y);
title('Acyclic Convolution: Rectangular Window'), xlabel('Time'), ylabel('Convolved
Signals');

end

Process:
First, I tested the program using two numerical vectors of length 32 with the following
values:

x = rand(1, 32);
h = linspace(0, 1, 32);

and a window size (N value) of 8. Using the plot produced by the program, we can see
the results:
Acyclic convolution using rectangular windows

Following this, I read two audio files into the x and h vectors (both original audio files
are available on the website):

x = wavread(flute2.wav);
h = wavread(short_beat.wav);

Using the convolution program with a window size of 2048, I convolved the two signals
together to produce a signal that could be written to an output audio file using the
following commands:

y = acyc_win_conv(x, h, 2048);
wavwrite(y, 44100, 16, acyc_win_conv.wav);

The output file acyc_win_conv.wav is available on the website to listen to.

Discussion:
Most of these methods (with the exception of the time domain methods) have a minimal
runtime. The most refined method, which can be heard in its output track, is the raised
cosine windowing method (part c). The other methods give a primitive, noisy sound and
the time saved is not worth the loss of quality.

Part 2
Take the FFT of a cosine wave, which has an integer number of samples per cycle (e.g 8)
and plot the result (both amplitude and phase). For example with 8 KHz sampling rate,
use 1 KHz cosine wave.

The following Matlab program was used to derive all the following cosine waves and
FFTs (and their respective plots). The fc (center frequency) and fft_size parameters are
adjusted accordingly for each question (this software is also available on the website):

% Create a cosine wave with center frequency fc and take its fft
% The win_flag sets whether or not to do cosine windowing
function Y = my_fft(fc, fft_size, win_flag)

% Set the sampling rate, period, wavelength, and timescale


fs = 8000;
N = 1/fs;
L = fs;
n = (0:L-1)*N;

% Create a cosine wave and plot


wave = cos(2*pi*fc*n);
subplot(3, 1, 1);
plot(fs*n(1:100), wave(1:100));
title('Cosine Wave'), xlabel('Time'), ylabel('Amplitude');

% If the windowing flag is set, do cosine windowing


if(win_flag==1)

% Create the raised cosine function


rcos_win = 1/2*(1-cos(2*pi*(1:fft_size)/fft_size));

% Initialize output signal


Y = zeros(1, length(wave));

for n=1:fft_size:length(wave)

if(n+fft_size>=length(wave))
% Account for shorter segment (last one)
wave_i = wave(n:length(wave));
rcos_win = 1/2*(1-cos(2*pi*(1:length(wave)-n+1)/(length(wave)-n+1)));
else
% Partition the signal into size N
wave_i = wave(n:n+fft_size-1);
end

% Piecewise multiply the input segment with the cosine function


wave_rcos = wave_i .* rcos_win;

% Perform a circular shift on the time domain segment


wave_rcos_shft = circshift(wave_rcos, [0, fft_size/2]);

% Take the fft of the windowed input


Y_temp = fft(wave_rcos_shft);

% Make the segment an even length


if(mod(length(Y_temp), 2)>0)
Y_temp(length(Y_temp)+1) = 0;
end

% Get the length value


len = length(Y_temp);

% Overlap add the first half of the output (after first pass)
if(n>1)
Y(n:n+len/2-1) = Y(n:n+len/2-1) + Y_temp(1:len/2);
elseif(n==1)
Y(n:n+len-1) = Y_temp;
continue;
end

% Add the "new" values to the output


Y(n+len/2:n+len-1) = Y_temp(len/2+1:len);
end
else
% Take the fft of the cosine wave (without windowing)
Y = fft(wave, fft_size)/L;
end

% Create the fft scale


f = fs/2*linspace(0, 1, fft_size/2+1);

% Plot the magnitude spectrum


subplot(3, 1, 2);
stem(f, 2*abs(Y(1:fft_size/2+1)));
title('FFT Magnitude'),xlabel('Frequency (Hz)'), ylabel('|Y(n)|');

% Plot the fft phase


subplot(3, 1, 3);
plot(f, angle(Y(1:fft_size/2+1)));
title('FFT Phase'),xlabel('Frequency (Hz)'),ylabel('Omega');

end

The first cosine and its FFT are given by the following parameters:

Sampling rate (fs) = 8000Hz (same throughout)


Center frequency (fc) = 1000Hz
FFT size = 8

It is shown in the plots below:


- Repeat for a different FFT block size, e.g. 256.

The second cosine and its FFT are given by the following parameters:

fc = 1000Hz
FFT size = 256

It is shown in the plots below:


- Repeat for a cosine wave with a non-integer number of samples per cycle.

The third cosine and its FFT are given by the following parameters:

fc = 976Hz
FFT size = 256

It is shown in the plots below:


- Repeat again after windowing the cosine wave with a raised cosine window (256
sample window).

The fourth cosine and its FFT are given by the following parameters:

fc = 976Hz
FFT size = 256
Cosine window size = 256

It is shown in the plots below:


- Repeat again after shifting the cosine wave by 90 degrees (e.g. use sine instead).

(For this question, the above code was simply modified so that the cos wave became a sin
wave)

The fifth wave and its FFT are given by the following parameters:

fc = 976Hz
FFT size = 256
Cosine window size = 256

It is shown in the plots below:


- Explain all results

The first three sets of plots are all similar, however the initial two sets are less accurate
due to poorer resolution. The third set of plots is ideal. The fourth and fifth sets of plots
represent a more accurate fft magnitude spectrum (were a greater resolution required),
however, due to the cosine windowing, phase-smearing has occurred, which is obvious in
the third plot of each set.

Вам также может понравиться