I am trying to understand how the MATLAB FFT normalization works.
Lets discuss the following example.
%%
sum2D = #(a) sum(reshape(a,1,[])); % sum elements in 2D matrix
a = [0 0 0; 1 2 1; 1 1 1; 1 1 1; 0 0 0]
f1 = fft2(a)
m = [0 32 0; 0 0 0; 0 1 0; 0 2 0; 0 0 0]
fs = m.*fftshift(f1);
fs = fs./sqrt(numel(fs));
fm = ifft2(fs);
fm = fm.*sqrt(numel(fm))
% imshow(abs(fs))
norm(a(:))^2,norm(fs(:))^2,norm(fm(:))^2
sum2D(abs(a).^2)
sum2D(abs(fs).^2)
sum2D(abs(fm).^2)
sum2D(abs(fp).^2)
If the m = 1, the normalization works and the energy is the same in the initial signal, fft and inverse fft. But if I multiply the signal after making fft by some vector m, then I don't know how to normalize this again.
Should the energy change after multiplying with the m, or I am doing something wrong.
Yes, multiplying the frequencies by matrix m changes the energy. You have amplified some frequencies and killed others: this may well make the signal stronger or weaker. As a simple example, suppose m had all entries equal to 2: then you double the signal, multiplying its energy by 4. For a general multiplier m, the effect on the energy will depend on what the signal is.
If you really want fm to have the same energy as a, just make it so:
fm = fm*norm(a(:))/norm(fm(:));
To directly answer "how FFT normalization works": applying fft2 multiplies the energy by the number of elements of the matrix. The function ifft2, being the inverse of fft2, divides the energy by the number of elements. So, if you are using ifft2 after fft2 and don't care about intermediate results such as fs, you don't need to do any division or multiplication by sqrt(numel(...)).
Related
Plot 2 discrete signals:
x[n] = delta[n] - delta[n-1] + delta[n+4]
y[n] = 0.5^n*u[n]
Also plot the convolution.
I don't know what the delta is supposed to be and how to approach these kind of signals. If I have a simple signal, I know how to do it.
n = 0:7;
x1 = cos(pi*n);
subplot(1,2,1)
stem(n,x1)
Using the dirac (delta) function in matlab will not work for discrete functions as the outcome is Inf at n=0. Instead use the value 1 at the right locations. Furthermore, u[n] is the step function or in matlab the heaviside function. It is zero for negative x and 1 for positive x, making a step at exactly x = 0.
The following code will plot all your functions:
n = -5:5
x = [0 1 0 0 0 1 1 0 0 0 0]; %x[n] from n =-5 to n=5
%y = 0.5.^n .* heaviside(n); %[y[n] from n =-5 to n=5
y = 0.5.^n .* [0 0 0 0 0 1 1 1 1 1 1]; %stepfunction from n =-5 to n=5
z = conv(x,y); %z[n] from n = -10 to n=10
subplot(3,1,1);stem(n,y1)
subplot(3,1,2);stem(n,y2)
subplot(3,1,3);stem(-10:10,y3)
It appears to the be the Dirac delta function. Which has a function in Matlab.
x = dirac(n)
Also, the convolution of two functions has a function.
w = conv(u,v)
Not knowing the interval you have for these, I can't say. I could generate some code. Also the function u is unknown.
I was given the original sine wave(Image 1) and a noisy version of it too(Image 2).
Image 1
Image 2
Now to find the original signal, I am looking at the frequency in the first half of the graph which has the greatest value. This would be 21. When I try to create a sine wave with 21 as a frequency using the code below, I get the result of Image 3.
% Creating the Sine Wave
t = (1:1:256);
A = 1;
y = A*sin(2*pi*max_index*t);
plot(t,y);
Image 3
Why is this the case. What am I doing wrong?
RUNNABLE CODE
Here is my Function:
function [ ] = function1b( Sig_noise )
% Max Index is the frequency of the pure tone
noise_f = fft(Sig_noise);
s_nf = size(noise_f);
size_f = s_nf(2);
max = 0;
max_index = 1;
for n = 1:(size_f/2)
if abs(noise_f(n)) > max
max = abs(noise_f(n));
max_index = n;
end
end
% Creating the Sine Wave
t = (1:1:256);
A = 1;
y = A*sin(2*pi*max_index*t);
plot(t,y);
end
And I am calling it from this part of the script:
load('Sig'); % Original Signal
Sig_noise2=awgn(Sig,10);
function1b(Sig_noise2);
Andras' Solution
This is the result I seem to be getting:
Using linspace(0,2,100); gives me this result:
Your code says
t = (1:1:256);
A = 1;
y = A*sin(2*pi*max_index*t);
While your amplitude is nice and big and 1, if max_index is integer then your phase inside the sin is an integer multiple of 2*pi for every t, which is exactly zero. This is why your function is numerically zero. You need the frequency of the max index:
y = A*sin(2*pi*freq(max_index)*t);
if the frequencies are stored in freq, or if max_index already stands for a frequency, then use a denser t mesh, like
t = linspace(1,256,1000);
You might be misinterpreting the output of fft. From help fft:
For length N input vector x, the DFT is a length N vector X,
with elements
N
X(k) = sum x(n)*exp(-j*2*pi*(k-1)*(n-1)/N), 1 <= k <= N.
n=1
The inverse DFT (computed by IFFT) is given by
N
x(n) = (1/N) sum X(k)*exp( j*2*pi*(k-1)*(n-1)/N), 1 <= n <= N.
k=1
That means that the frequencies are not max_index, but (max_index-1)/N if your original sample has N points. This turns your flawed large frequency into the actual small frequency, solving your issues.
To break it down to you: try
t = 1:256;
y = A*sin(2*pi*(max_index-1)/length(Sig_noise)*t);
I guess there is some problem in sampling rate.
replace
t=(1:1:256)
with
t = (1:1/(f*3):3)
Here f=max_index =21
Consider we have 4 vectors, V1,V2,nf1 and nf2. We need to generate n=8736 random numbers that each pair of (V1,V2) , (V1,nf1), (V2,nf2) and (nf1,nf2) to be correlate as follow:
Rvv=0.6 for (V1,V2)
Rvn=0.5 for (V1,nf1) and (V2,nf2)
Rnn=0 for (nf1,nf2)
(It's not important what correlation of (V1,nf2) and (V2, nf1) is). Now we use copula to generate correlated random numbers in MATLAB:
Rvv=0.6;
Rvn=0.5;
Rnn=0;
n = 8736;
%V1 V2 nf1 nf2
Rho = [1 Rvv Rvn 0 ; %V1
Rvv 1 0 Rvn; %V2
Rvn 0 1 Rnn; %nf1
0 Rvn Rnn 1 ]; %nf2
Random_no = copularnd('Gaussian',Rho,n);
It's all OK when Rvv is 0.6, and Random_no will be a 8736 by 4 matrix, that each pair of columns are correlated as we specified by Rho Matrix. BUT when Rvv=0.9, MATLAB returns error as follow:
Error using mvnrnd
SIGMA must be a symmetric positive semi-definite matrix.
Error in copularnd
u = normcdf(mvnrnd(zeros(1,d),Rho,n));
I can't understand what the problem is and how can I really generate correlated random numbers using copula. I'll really appreciate if anyone can help me through this problem.
I can't answer about theory, but got this in code of copularnd:
case 'gaussian'
Rho = varargin{1};
n = varargin{2};
d = size(Rho,1);
if isscalar(Rho)
if ~(-1 < Rho && Rho < 1)
error(message('stats:copularnd:BadScalarCorrelation'));
end
Rho = [1 Rho; Rho 1];
d = 2;
elseif any(diag(Rho) ~= 1)
error(message('stats:copularnd:BadCorrelationMatrix'));
end
% MVNRND will check that Rho is square, symmetric, and positive semi-definite.
u = normcdf(mvnrnd(zeros(1,d),Rho,n));
Because of there no any information about it in help, I think it must be clearly for people who knows what copula is :) but is not for me
There are a lot of ways to generate positive semi-definite matrices: http://www.mathworks.com/matlabcentral/newsreader/view_thread/163489
I'm not sure if this typical behaviour or not but I am solving a finite-difference problem using the backward differencing method.
I populated a sparse matrix with the appropriate diagonal terms (along the central diagonal and one above and below it) and I attempted to solve the problem using MATLAB's built-in method (B=A\x) and it seems MATLAB just gets it wrong.
Furthermore, if use inv() and use the inverse of the tridiagonal matrix I get the correct solution.
Why does this behave like this?
Additional info:
http://pastebin.com/AbuEW6CR (Values are tabbed so its easier read)
Stiffness matrix K:
1 0 0 0
-0.009 1.018 -0.009 0
0 -0.009 1.018 -0.009
0 0 0 1
Values for d:
0
15.55
15.55
86.73
Built-in output:
-1.78595556155136e-05
0.00196073713853244
0.00196073713853244
0.0108149483252210
Output using inv(K):
0
15.42
16.19
86.73
Manual output:
0
15.28
16.18
85.16
Code
nx = 21; %number of spatial steps
nt = 501; %number of time steps (varies between 501 and 4001)
p = alpha * dt / dx^2; %arbitrary constant
a = [0 -p*ones(1,nx-2) 0]'; %diagonal below central diagonal
b = (1+2*p)*ones(nx,1); %central diagonal
c = [1 -p*ones(1,nx-2) 1]'; %diagonal above central diagonal
d = zeros(nx, 1); %rhs values
% Variables a,b,c,d are used for the manual tridiagonal method for
% comparison with MATLAB's built-in functions. The variables represent
% diagonals and the rhs of the matrix
% The equation is K*U(n+1)=U(N)
U = zeros(nx,nt);
% Setting initial conditions
U(:,[1 2]) = (60-32)*5/9;
K = sparse(nx,nx);
% Indices of the sparse matrix which correspond to the diagonal
diagonal = 1:nx+1:nx*nx;
% Populating diagonals
K(diagonal) =1+2*p;
K(diagonal(2:end)-1) =-p;
K(diagonal(1:end-1)+1) =-p;
% Applying dirichlet condition at final spatial step, the temperature is
% derived from a table for predefined values during the calculation
K(end,end-1:end)=[0 1];
% Applying boundary conditions at first spatial step
K(1,1:2) = [1 0];
% Populating rhs values and applying boundary conditions, d=U(n)
d(ivec) = U(ivec,n);
d(nx) = R; %From table
d(1) = 0;
U(:,n+1) = tdm(a,b,c,d); % Manual solver, gives correct answer
U(:,n+1) = d\K; % Built-in solver, gives wrong answer
The following line:
U(:,n+1) = d\K;
should have been
U(:,n+1) = K\d;
By mistake I had them the wrong way round and didn't notice it, it obviously changes the mathematical expression and hence the wrong answers.
I am new to MATLAB and I am trying to built a voice morphing system using MATLAB.
So I would like to know how to normalize a signal to zero mean and unit variance using MATLAB?
if your signal is in the matrix X, you make it zero-mean by removing the average:
X=X-mean(X(:));
and unit variance by dividing by the standard deviation:
X=X/std(X(:));
If you have the stats toolbox, then you can compute
Z = zscore(S);
You can determine the mean of the signal, and just subtract that value from all the entries. That will give you a zero mean result.
To get unit variance, determine the standard deviation of the signal, and divide all entries by that value.
It seems like you are essentially looking into computing the z-score or standard score of your data, which is calculated through the formula: z = (x-mean(x))/std(x)
This should work:
%% Original data (Normal with mean 1 and standard deviation 2)
x = 1 + 2*randn(100,1);
mean(x)
var(x)
std(x)
%% Normalized data with mean 0 and variance 1
z = (x-mean(x))/std(x);
mean(z)
var(z)
std(z)
To avoid division by zero!
function x = normalize(x, eps)
% Normalize vector `x` (zero mean, unit variance)
% default values
if (~exist('eps', 'var'))
eps = 1e-6;
end
mu = mean(x(:));
sigma = std(x(:));
if sigma < eps
sigma = 1;
end
x = (x - mu) / sigma;
end