MATLAB made me feel like a GOD
Forgive me for the caption, but I am aware of MATLAB's reputation being everyone's favorite, ( MATLAB is favored by only 20% of it's users ) but I have been using it heavily in my Electronics Engineering courses. { MATLAB is so bad that even Hashnode didn't provide syntax highlighting for it's codes }
Problem
I was transmitting 5 unique signals and receiving them through a speaker kept at a distance of 3m, then 5m, then 7m. So I had a total of 15 audio signals received and had them all names as :-
"3_r1.wav"
"3_r2.wav"
"3_r3.wav"
"3_r4.wav"
"3_r5.wav"
and so on for the other 2 sets of audio files.
So this is what I had to do, for each of the 15 signals :-
Get a figure with subplots of
Transmitted signal's time domain representation
Transmitted signal's frequency profile
Received signal's entire time domain representation
Received signal's frequency profile
Received signal's time domain but magnified
Generate an EPS file for report
The plot for this transmitted signal when received at a distance of 3m is given below.
$$y = 0.8 \times \text{sawtooth}(2 \pi \times 2000 \times t)$$
I had to do this for each of the 15 signals.
And the code that I wrote to d0 this ( apart from being ugly and cluttered, since this was done in a hurry ) had too many places where I need to make to change to generate the figure of next signal.
( You don't have to read this to understand the solution, that I got ; The intent was only to show it was pretty hard to get figure of one single figure )
clc ;
clear;
close all ;
% DO THIS FOR EACH OF SIGNALS FIRST
$ - change the file_name of audio.wav
% - change y
% - change color of plot
% - change y_interval
% - chagne the title of each subplot accordingly
fs_ = 48000;
duration_ = 10;
t__ = linspace(0,duration_ ,fs_ * duration_);
y = 0.8*sawtooth(2 * pi * 2000 * t__, 0.5);
% Define the time interval for clearer visualization
start_time = 5;
end_time = 5.005;
duration = end_time - start_time;
% Generate time vector for the specified interval
t_interval = linspace(start_time, end_time, fs_ * duration);
y_interval = 0.8*sawtooth(2 * pi * 2000 * t_interval, 0.5);
% Load the WAV file
[y, fs] = audioread('./DSP project/3_r4.wav');% Calculate the time axis
num_samples = length(y);
time_axis = (0:num_samples-1) / fs;
Y = fftshift(fft(y));
f_axis = -fs/2:fs/(length(Y)-1):fs/2;
f_axis = f_axis';
% Convert start and end times to sample indices
start_index = round(start_time * fs) + 1;
end_index = round(end_time * fs);
% Extract samples from the specified time range
y_subset = y(start_index:end_index);
time_subset = time_axis(start_index:end_index);
figure('NumberTitle', 'off', 'Name', 'This is the figure title');
subplot(5,1,1);
plot(t_interval, y_interval, 'm');
title('Time Domain - Signal 1');
xlabel('Time (s)');
ylabel('Amplitude');
title('Time-domain representation of Transmitted signal');
% Plot the frequency-domain representation
subplot(5,1,2);
Y1 = fftshift(fft(y));
frequencies = linspace(-fs/2, fs/2, length(Y1));
plot(frequencies, abs(Y1), 'm');
title('Frequency Domain - Signal 1');
xlabel('Frequency (Hz)');
ylabel('Magnitude');
title('Frequency-domain representation of Transmitted signal');
% Plot the time-domain representation
subplot(5,1,3);
plot(time_axis, y,'k');
xlabel('Time (seconds)');
ylabel('Amplitude');
title('Time-domain representation of Recieved signal at 3m');
% Plot the frequency-domain representation
subplot(5,1,4);
plot(f_axis, abs(Y),'k');
xlabel('Frequency (Hz)');
ylabel('Magnitude');
title('Frequency-domain representation of Recieved signal at 3m');
% Plot the subset of the time signal
subplot(5,1,5);
plot(time_subset, y_subset,'k');
xlabel('Time (seconds)');
ylabel('Amplitude');
title('A very small subset of time domain signal for clarity');
print(gcf, '-depsc', '3_4.eps');
I ran the code for first 2 signals and it took 20 minutes. But I had fixed all the bugs and had the code pretty much all-set with changes having to only at the below 4 places.
Friction created
% DO THIS FOR EACH OF SIGNALS FIRST
$ - change the file_name of audio.wav
% - change y
% - change color of plot
% - change y_interval
% - chagne the title of each subplot accordingly
It would have only taken 5 minutes to get the remaining 13 figures.
But,
I am an engineer,
that means I gotta :-
Spend another half an hour trying to automate something that would only take me one-third of the time trying to figure out how to automate.
So I spend next half an hour trying to automate the entire process.
Solution : Power of Array of Anonymous functions
My computer science undergrad peers and other tech influencers love to talk about this coding principle :-
DRY : Don't repeat yourself
The solution that I came up ( totally not using Chat-GPT ) upholds that very principle ( but not in the way it's traditionally implemented with the functional blocks, etc. )
% 3 automation magic :-
% 1
signals = {@(t) 1*cos(2*pi*5000*t), ...
@(t) 0.9*sin(2*pi*1000*t), ...
@(t) 0.5*sin(2*pi*3000*t)+0.3*cos(2*pi*6000*t), ...
@(t) 0.8*sawtooth(2 * pi * 2000 * t, 0.5), ...
@(t) 0.3*cos(2*pi*5000*t) + 0.1 * randn(size(t))};
% 2
colors = {'r', 'g', 'b', 'm', 'c'};
% 3
received_files = {'./DSP_PROJECT/3_r1.wav', ...
'./DSP_PROJECT/3_r2.wav', ...
'./DSP_PROJECT/3_r3.wav', ...
'./DSP_PROJECT/3_r4.wav', ...
'./DSP_PROJECT/3_r5.wav'};
Signals is an array of anonymous functions.
Now I could -
y = signals{i}(t);
and get it's corresponding color by :-
plot(frequencies, abs(Y), colors{i});
And string manipulate in titles according to the value of `i`
So here is the code that made me feel like God :-
clc;
clear;
close all;
% 3 automation magic :-
% 1
signals = {@(t) 1*cos(2*pi*5000*t), ...
@(t) 0.9*sin(2*pi*1000*t), ...
@(t) 0.5*sin(2*pi*3000*t)+0.3*cos(2*pi*6000*t), ...
@(t) 0.8*sawtooth(2 * pi * 2000 * t, 0.5), ...
@(t) 0.3*cos(2*pi*5000*t) + 0.1 * randn(size(t))};
% 2
colors = {'r', 'g', 'b', 'm', 'c'};
% 3
received_files = {'./DSP_PROJECT__1/3_r1.wav', ...
'./DSP_PROJECT__1/3_r2.wav', ...
'./DSP_PROJECT__1/3_r3.wav', ...
'./DSP_PROJECT__1/3_r4.wav', ...
'./DSP_PROJECT__1/3_r5.wav'};
for i = 1:numel(signals)
fs_generated = 48000;
duration_ = 10;
t = linspace(0,duration_ ,fs_generated * duration_);
y1 = signals{i}(t);
% Time interval for clearer Visualization
start_time = 4;
end_time = 4.002;
duration = end_time - start_time;
% Generating time vector for THAT specified interval
t1_interval = linspace(start_time, end_time, fs_generated * duration);
y1_interval = signals{i}(t1_interval);
% Define subplot title according to signal
subplot_title = sprintf('Signal - %d', i);
% Plot time-domain representation of TRANSMITTED SIGNAL
figure;
subplot(5, 1, 1);
plot(t1_interval, y1_interval, colors{i});
title(['Time Domain - ' subplot_title]);
xlabel('Time (s)');
ylabel('Amplitude');
% Plot frequency-domain representation of TRANSMITTED SIGNAL
subplot(5, 1, 2);
Y1 = fftshift(fft(y1));
frequencies = linspace(-fs_generated/2, fs_generated/2, length(Y1));
plot(frequencies, abs(Y1), colors{i});
title(['Frequency Domain - ' subplot_title]);
xlabel('Frequency (Hz)');
ylabel('Magnitude');
% Read received signal and extract subset
[y_received, fs_received] = audioread(received_files{i});
num_samples = length(y_received);
time_axis_received = (0:num_samples-1) / fs_received;
% Plot time domain of RECEIVED SIGNAL
subplot(5, 1, 3);
plot(time_axis_received, y_received, 'k');
xlabel('Time (s)');
ylabel('Amplitude');
title(['Time-domain representation of Received signal at 3m - ' subplot_title]);
Y_received = fftshift(fft(y_received));
f_axis_received = -fs_received/2 : fs_received/(length(Y_received)-1) : fs_received/2;
f_axis_received = f_axis_received';
subplot(5, 1, 4);
plot(f_axis_received, abs(Y_received), 'k');
xlabel('Frequency (Hz)');
ylabel('Magnitude');
title(['Frequency-domain representation of Received signal at 3m - ' subplot_title]);
% Indexes corresponding to start and end time
start_index = round(start_time * fs_received ) + 1;
end_index = round(end_time * fs_received );
% Extract samples from the specified time range
y_subset = y_received(start_index:end_index);
time_subset = time_axis_received(start_index:end_index);
subplot(5, 1, 5);
plot(time_subset, y_subset, 'k');
xlabel('Time (s)');
ylabel('Amplitude');
title(['Subset of Received signal for clarity - ' subplot_title]);
% Save figure as EPS file
print(gcf, '-depsc', sprintf('1_%d.eps', i));
end
This was my first blog and I realize it was pretty bad.
The intent of this Diary is purely to keep a public journal of my growth, I need to put in way more effort if my aim was to contribute something meaningful, and I believe I have a long way still to go. But let's see how long I can keep this up.
Any correction, or comments are appreciated,
Thank you for reading my dumpster fire.
Subscribe to my newsletter
Read articles from __CPP__Try_Hard__ directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
__CPP__Try_Hard__
__CPP__Try_Hard__
A Try Hard to the core ;