Fourier series not plotting correct amplitude - matlab

I am trying to plot a 10% duty cycle square wave using matlab, but for some reason the amplitude of the series changes in a unpredictable way for different values of N. I was expecting the amplitude to be 1 (i.e. from [-1;1]. I am not sure what to change?
% Assignment of variables
syms t
[enter image description here][1]
% Function variables
N = 5;
T0 = 1;
w0 = 2*pi/T0;
Imin1 = 0;
Imax1 = 0.1;
% If square wave with mean at 0
bool = 1;
Imin2 = 0.1;
Imax2 = 1;
% Function
ft = 1;
% First term calculation
a0 = (1/T0)*int(ft, t, Imin1, Imax1) + (bool)*(1/T0)*int((-ft), t, Imin1, Imax1);
y = a0;
% Calculation of n terms
for n = 1:N
an = (2/T0)*int(ft*cos(n*w0*t), t, Imin1, Imax1) + (bool)*(2/T0)*int((-ft)*cos(n*w0*t), t, Imin2, Imax2);
bn = (2/T0)*int(ft*sin(n*w0*t), t, Imin1, Imax1) + (bool)*(2/T0)*int((-ft)*sin(n*w0*t), t, Imin2, Imax2);
y = y + an*cos(n*w0*t) + bn*sin(n*w0*t);
end
fplot(y, [0,4], "Black")

Related

Changing amplitude of fourier series in matlab

The code below currently plots the fourier series for a square wave for N terms. Is there any way I could change the range from [0;1] to [-1;1]?
% Assignment of variables
syms t
% Function variables
N = 5;
T0 = 1;
w0 = 2*pi/T0;
Imin = 0;
Imax = 0.5;
% Function
ft = 1;
% First term calculation
a0 = (1/T0)*int(ft, t, Imin, Imax);
y = a0;
% Calculation of n terms
for n = 1:N
an = (2/T0)*int(ft*cos(n*w0*t), t, Imin, Imax);
bn = (2/T0)*int(ft*sin(n*w0*t), t, Imin, Imax);
y = y + an*cos(n*w0*t) + bn*sin(n*w0*t);
end
fplot(y, [-4,4], "Black")
grid on
If you are talking about the figure scale, then ylim([-1 1])
1.- The following does what you asked for:
clear all;clc;close all
syms t
assume(t>0 & t<1)
% Function variables
N = 5;
T0 = 1;
w0 = 2*pi/T0;
Imin = 0;
Imax = 1;
% Function
h1=heaviside(t-.5)
h2=heaviside(t+.5)
ht=-2*((h1-h2)+.5)
% First term calculation
a0 = (1/T0)*int(ht, t, Imin, Imax);
y = a0;
% Calculation of n terms
for n = 1:N
an = (2/T0)*int(ht*cos(n*w0*t), t, Imin, Imax);
bn = (2/T0)*int(ht*sin(n*w0*t), t, Imin, Imax);
y = y + an*cos(n*w0*t) + bn*sin(n*w0*t);
end
fplot(y, [-4,4], "Black")
grid on
2.- You allocate a specific group of code lines headed with % Function to precisely define the function.
Yet you actually define the function with Imin and Imax.
It's good practice to constrain the function definition within the lines you intend for such purpose, not to scatter the function all over the place.

Preventing using for loop in MATLAB

I have written the below MATLAB code. I want to know how can I optimize it without using for loop.
Any help will be very appreciated.
MATLAB code:
%Some parameters:
s = 50;
k = 50;
r = 0.1;
v = 0.2;
t = 2;
n=10000;
% Calculate CT by calling EurCall function
CT = EurCall(s, k, r, v, t, n);
%Function EurCall to be called
function C = EurCall(s, k, r, v, t, n)
X = zeros(n,1);
hh = zeros(n,1);
for ii = 1 : n
X(ii) = normrnd(0, 1);
SS = s*exp((r - v^2/2)*t + v*X(ii)*sqrt(t));
hh(ii) = exp(-r*t)*max(SS - k, 0);
end %end for loop
C = (1/n) * sum(hh);
end %end function
Vectorized Approach:
Here is a vectorized approach that I think replicates the same functionality as the original script. Instead of looping this example declares X as a vector of size n by 1. By using element-wise multiplication .* we can effectively calculate the remaining vectors SS and hh without need to loop through the indices. In this case SS and hh will also be vectors of size n by 1. I do agree with comment above that MATLAB's for-loops are no longer inherently slow.
%Some parameters:
s = 50;
k = 50;
r = 0.1;
v = 0.2;
t = 2;
n=10000;
% Calculate CT by calling EurCall function
[CT] = EurCall(s, k, r, v, t, n);
%Function EurCall to be called
function [C] = EurCall(s, k, r, v, t, n)
X = zeros(n,1);
hh = zeros(n,1);
mu = 0; sigma = 1;
%Creating a vector of normal random numbers of size (n by 1)%
X = normrnd(mu,sigma,[n 1]);
SS = s*exp((r - v^2/2)*t + v.*X.*sqrt(t));
hh = exp(-r*t)*max(SS - k, 0);
C = (1/n) * sum(hh);
end %end function
Ran using MATLAB R2019b

Finding Percent Error of a Fourier Series

Find the error as a function of n, where the error is defined as the difference between two the voltage from the Fourier series (vF (t)) and the value from the ideal function (v(t)), normalized to the maximum magnitude (Vm ):
I am given this prompt where Vm = 1 V. Below this line is the code which I have written.
I am trying to write a function to solve this question: Plot the error versus time for n=3,n=5,n=10, and n=50. (10points). What does it look like I am doing incorrectly?
clc;
close all;
clear all;
% define the signal parameters
Vm = 1;
T = 1;
w0 = 2*pi/T;
% define the symbolic variables
syms n t;
% define the signal
v1 = Vm*sin(4*pi*t/T);
v2 = 2*Vm*sin(4*pi*t/T);
% evaluate the fourier series integral
an1 = 2/T*int(v1*cos(n*w0*t),0,T/2) + 2/T*int(v2*cos(n*w0*t),T/2,T);
bn1 = 2/T*int(v1*sin(n*w0*t),0,T/2) + 2/T*int(v2*sin(n*w0*t),T/2,T);
a0 = 1/T*int(v1,0,T/2) + 1/T*int(v2,T/2,T);
% obtain C by substituting n in c[n]
nmax = 100;
n = 1:nmax;
a = subs(an1);
b = subs(bn1);
% define the time vector
ts = 1e-2; % ts is sampling the
t = 0:ts:3*T-ts;
% directly plot the signal x(t)
t1 = 0:ts:T-ts;
v1 = Vm*sin(4*pi*t1/T).*(t1<=T/2);
v2 = 2*Vm*sin(4*pi*t1/T).*(t1>T/2).*(t1<T);
v = v1+v2;
x = repmat(v,1,3);
% Now fourier series reconstruction
N = [3];
for p = 1:length(N)
for i = 1:length(t)
for k = N(p)
x(k,i) = a(k)*cos(k*w0*t(i)) + b(k)*sin(k*w0*t(i));
end
% y(k,i) = a0+sum(x(:,i)); % Add DC term
end
end
z = a0 + sum(x);
figure(1);
plot(t,z);
%Percent error
function [per_error] = percent_error(measured, actual)
per_error = abs(( (measured - actual) ./ 1) * 100);
end
The purpose of the forum is helping with specific technical questions, not doing your homework.

Mel-frequency function: error with matrix dimensions

I'm trying to make a prototype audio recognition system by following this link: http://www.ifp.illinois.edu/~minhdo/teaching/speaker_recognition/. It is quite straightforward so there is almost nothing to worry about. But my problem is with the mel-frequency function. Here is the code as provided on the website:
function m = melfb(p, n, fs)
% MELFB Determine matrix for a mel-spaced filterbank
%
% Inputs: p number of filters in filterbank
% n length of fft
% fs sample rate in Hz
%
% Outputs: x a (sparse) matrix containing the filterbank amplitudes
% size(x) = [p, 1+floor(n/2)]
%
% Usage: For example, to compute the mel-scale spectrum of a
% colum-vector signal s, with length n and sample rate fs:
%
% f = fft(s);
% m = melfb(p, n, fs);
% n2 = 1 + floor(n/2);
% z = m * abs(f(1:n2)).^2;
%
% z would contain p samples of the desired mel-scale spectrum
%
% To plot filterbanks e.g.:
%
% plot(linspace(0, (12500/2), 129), melfb(20, 256, 12500)'),
% title('Mel-spaced filterbank'), xlabel('Frequency (Hz)');
f0 = 700 / fs;
fn2 = floor(n/2);
lr = log(1 + 0.5/f0) / (p+1);
% convert to fft bin numbers with 0 for DC term
bl = n * (f0 * (exp([0 1 p p+1] * lr) - 1));
b1 = floor(bl(1)) + 1;
b2 = ceil(bl(2));
b3 = floor(bl(3));
b4 = min(fn2, ceil(bl(4))) - 1;
pf = log(1 + (b1:b4)/n/f0) / lr;
fp = floor(pf);
pm = pf - fp;
r = [fp(b2:b4) 1+fp(1:b3)];
c = [b2:b4 1:b3] + 1;
v = 2 * [1-pm(b2:b4) pm(1:b3)];
m = sparse(r, c, v, p, 1+fn2);
But it gave me an error:
Error using * Inner matrix dimensions must agree.
Error in MFFC (line 17) z = m * abs(f(1:n2)).^2;
When I include these 2 lines just before line 17:
size(m)
size(abs(f(1:n2)).^2)
It gave me :
ans =
20 65
ans =
1 65
So should I transpose the second matrix? Or should I interpret this as an row-wise multiplication and modify the code?
Edit: Here is the main function (I simply run MFCC()):
function result = MFFC()
[y Fs] = audioread('s1.wav');
% sound(y,Fs)
Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
spectrum = FFT_After_Windowing(Windowed);
%imagesc(mag2db(abs(spectrum)))
p = 20;
S = size(spectrum);
n = S(2);
f = spectrum;
m = melfb(p, n, Fs);
n2 = 1 + floor(n/2);
size(m)
size(abs(f(1:n2)).^2)
z = m * abs(f(1:n2)).^2;
result = z;
And here are the auxiliary functions:
function f = Frame_Blocking(y,N)
% Parameters: M = 100, N = 256
% Default : M = 100; N = 256;
M = fix(N/3);
Frames = [];
first = 1; last = N;
len = length(y);
while last <= len
Frames = [Frames; y(first:last)'];
first = first + M;
last = last + M;
end;
if last < len
first = first + M;
Frames = [Frames; y(first : len)];
end
f = Frames;
function f = Windowing(Frames)
S = size(Frames);
N = S(2);
M = S(1);
Windowed = zeros(M,N);
nn = 1:N;
wn = 0.54 - 0.46*cos(2*pi/(N-1)*(nn-1));
for ii = 1:M
Windowed(ii,:) = Frames(ii,:).*wn;
end;
f = Windowed;
function f = FFT_After_Windowing(Windowed)
spectrum = fft(Windowed);
f = spectrum;
Transpose s or transpose the resulting f (it's just a matter of convention).
There is nothing wrong with the melfb function you are using, merely with the dimensions of the signal in the example you are trying to run (in the commented lines 14-17).
% f = fft(s);
% m = melfb(p, n, fs);
% n2 = 1 + floor(n/2);
% z = m * abs(f(1:n2)).^2;
The example assumes that you are using a "colum-vector signal s". From the size of your Fourier transformed f (done via fft which respects the input signal dimensions) your input signal s is a row-vector signal.
The part that gives you the error is the actual filtering operation that requires multiplying a p x n2 matrix with a n2 x 1 column-vector (i.e., each filter's response is multiplied pointwise with the Fourier of the input signal). Since your input s is 1 x n, your f will be 1 x n and the final matrix to vector multiplication for z will give an error.
Thanks to gevang's anwer, I was able to find out my mistake. Here is how I modified the code:
function result = MFFC()
[y Fs] = audioread('s2.wav');
% sound(y,Fs)
Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
%spectrum = FFT_After_Windowing(Windowed');
%imagesc(mag2db(abs(spectrum)))
p = 20;
%S = size(spectrum);
%n = S(2);
%f = spectrum;
S1 = size(Windowed);
n = S1(2);
n2 = 1 + floor(n/2);
%z = zeros(S1(1),n2);
z = zeros(20,S1(1));
for ii=1: S1(1)
s = (FFT_After_Windowing(Windowed(ii,:)'));
f = fft(s);
m = melfb(p,n,Fs);
% n2 = 1 + floor(n/2);
z(:,ii) = m * abs(f(1:n2)).^2;
end;
%f = FFT_After_Windowing(Windowed');
%S = size(f);
%n = S(2);
%size(f)
%m = melfb(p, n, Fs);
%n2 = 1 + floor(n/2);
%size(m)
%size(abs(f(1:n2)).^2)
%z = m * abs(f(1:n2)).^2;
result = z;
As you can see, I naively assumed that the function deals with row-wise matrices, but in fact it deals with column vectors (and maybe column-wise matrices). So I iterate through each column of the input matrix and then combine the results.
But I don't think this is efficient and vectorized code. Also I still can't figure out how to do column-wise operations on the input matrix (Windowed - after the windowing step), instead of using a loop.

Can't recover the parameters of a model using ode45

I am trying to simulate the rotation dynamics of a system. I am testing my code to verify that it's working using simulation, but I never recovered the parameters I pass to the model. In other words, I can't re-estimate the parameters I chose for the model.
I am using MATLAB for that and specifically ode45. Here is my code:
% Load the input-output data
[torque outputs] = DataLogs2();
u = torque;
% using the simulation data
Ixx = 1.00;
Iyy = 2.00;
Izz = 3.00;
x0 = [0; 0; 0];
Ts = .02;
t = 0:Ts:Ts * ( length(u) - 1 );
[ T, x ] = ode45( #(t,x) rotationDyn( t, x, u(1+floor(t/Ts),:), Ixx, Iyy, Izz), t, x0 );
w = x';
N = length(w);
q = 1; % a counter for the A and B matrices
% The Algorithm
for k=1:1:N
w_telda = [ 0 -w(3, k) w(2,k); ...
w(3,k) 0 -w(1,k); ...
-w(2,k) w(1,k) 0 ];
if k == N % to handle the problem of the last iteration
w_dash(:,k) = (-w(:,k))/Ts;
else
w_dash(:,k) = (w(:,k+1)-w(:,k))/Ts;
end
a = kron( w_dash(:,k)', eye(3) ) + kron( w(:,k)', w_telda );
A(q:q+2,:) = a; % a 3N*9 matrix
B(q:q+2,:) = u(k,:)'; % a 3N*1 matrix % u(:,k)
q = q + 3;
end
% Forcing J to be diagonal. This is the case when we consider our quadcopter as two thin uniform
% rods crossed at the origin with a point mass (motor) at the end of each.
A_new = [A(:, 1) A(:, 5) A(:, 9)];
vec_J_diag = A_new\B;
J_diag = diag([vec_J_diag(1), vec_J_diag(2), vec_J_diag(3)])
eigenvalues_J_diag = eig(J_diag)
error = norm(A_new*vec_J_diag - B)
where my dynamic model is defined as:
function [dw, y] = rotationDyn(t, w, tau, Ixx, Iyy, Izz, varargin)
% The output equation
y = [w(1); w(2); w(3)];
% State equation
% dw = (I^-1)*( tau - cross(w, I*w) );
dw = [Ixx^-1 * tau(1) - ((Izz-Iyy)/Ixx)*w(2)*w(3);
Iyy^-1 * tau(2) - ((Ixx-Izz)/Iyy)*w(1)*w(3);
Izz^-1 * tau(3) - ((Iyy-Ixx)/Izz)*w(1)*w(2)];
end
Practically, what this code should do, is to calculate the eigenvalues of the inertia matrix, J, i.e. to recover Ixx, Iyy, and Izz that I passed to the model at the very begining (1, 2 and 3), but all what I get is wrong results.
Is the problem with using ode45?
Well the problem wasn't in the ode45 instruction, the problem is that in system identification one can create an n-1 samples-signal from an n samples-signal, thus the loop has to end at N-1 in the above code.