Resampling of time signal in MATLAB - matlab

I want to resample my signal with to new time. Currently the sampling time of my signal is 0.01s, and the size of my signal and time array is 1*90001.
I am trying to use resample(x,p,q) in MATLAB, but I am a little bit confused.
Can somebody suggest the right way to use this function and how to resample my data to rate of 0.02s instead of 0.01s?
Code - this is how I am trying to use resample, with example data.
t = [0:0.03:1];
x = sin(4*pi*t);
y = resample(x, 1, 2);
ty = resample(t,1,2);
figure (1);
stem(ty, y, 'r*');
hold on;
stem(t,x,'b')
hold off
Updated Code :
t = [0 2 3 7 8 9 10 11 12 17 18 19 20 24 25 26 27 28 29 31 32 33 35 37 41 ];
A = [0 0 1 2 3 5.2 0 -1.4 0 2 2.7 2 2.3 6 7.3 0 0 -8.6 0 1 1 2.5 3 4.8 2];
plot(t,A)
% Tx = min(diff(t));
Tx = 1:0.1:25;
B = interp1(t,A,Tx); %re-make example data to have decimal points on the x-axis
y = resample(B, 2, 1);
T = 0.05;
Ty = T / (2 / 1);
ty = (0:length(y)-1)*Ty;
% A = interp1(t,ref,t2);
% A = ref;
figure
plot(Tx,B,'b')
hold on
plot(ty,y,'r')
plot(t,A,'g')
hold off

First of all you do not need to resample time line.
It is much easier to define time sampling interval variable or sampling frequency variable: T = 0.03; Fs = 1/T;
So, x resampling you perform right way: y = resample(x, 1, 2); .
But the new time line must be reconstructed via adjusted sampling interval: Ty = T / (1 / 2); ty = (0:length(y)-1)*Ty;
The resample function is suitable only for uniformly time distributed data points. If your original points are non-uniformly distributed, you need:
Interpolate your x signal to the uniform time line with the smallest sampling interval from the original time line: Tx = min(diff(t)); . See for example interp1 function.
Resample your interpolated uniformly time distributed (sampled) signal to the new sampling interval ( resample function).

your original signal is sampled with uniform sampling interval of 10 ms and you want to decrease sampling down to 20 ms. Why don't you just take every second datapoint of your original signal?
y = x(1:2:end);
ty = t(1:2:end);
UPDATE
for non regularly spaced datasets it is possible to use function resample as it is shown here: https://au.mathworks.com/help/signal/ref/resample.html#bungoxs
you can try
fs = 1/0.02;
[y, ty] = resample(x, t, fs, 1, 2)

There is another way to resample in a lower frequency your data.
Use this code:
fs=1/(timesignal(2)-timesignal(1)); %for example 48000Hz
fs_resampled=100; % [Hz] example goal value
t_original = [0:1/fs:(1/fs*(length(signal)-1))];%current time signal
t_resampled = [0:1/fs_resampled:max(t_original)];%new time signal
Signal_resampled = interp1(t_original,signal,t_resampled,'spline');
I hope that's what you wanted.
Greetings

Related

Generate a Rectangular Pulse in MATLAB

I need to create a rectangular pulse with width = 7 and a range (-T/2, T/2) where T 59 msec.
I wrote this code but I'm not sure if that's correct.
w = 7;
T = 59;
t = -T/2:1:T/2;
rect = rectpuls(t, w);
plot(t, rect);
This code generates a rectangular pulse but I'm not sure if it's right. Also, I'm not quite sure what the t = -T/2:1:T/2; means. I mean the range is from -29.5 to 29.5 with step 1. When I set this to 0.1 or 0.01 my pulse is better. Why does this affect my output?
Note that the second thing I have to do is to create a periodic sequence of clock pulses. I don't know if this affects the way I must implement my initial rectangular pulse.
When you increase the number of increments a numerical function (such as Matlab rectpuls) uses in its process of discretizing the continuous, you'll have as consequence that the accuracy of said function is going to improve, at the expense (in this case, negligible) of added computational cost. You are doing exactly this, when you discretize employing smaller time-steps, from 1 to 0.1 to 0.01.
To create a periodic sequence of identical rectangular pulses, you can call the function in a loop:
w = 7;
T = 59;
t = -T/2:1:T/2;
t_size = size(t);
N = 10;
rect = zeros(N, t_size(2));
interval = 20;
figure
plot(t, rectpuls(t, w));
xlim([-20 (N + 1)*interval]);
ylim([0 1.1]);
hold on
for i = 1:N
t = (-T/2 + i*interval): 1 :(T/2 + i*interval);
rect(i,:) = rectpuls(t - i * interval, w);
plot(t, rect(i,:));
hold on
end
The above should generate identical rectangular pulses every interval = 20 ms, over a time length of interval * (N + 1) = 220 ms.

Save samples that repeat every 300 ms

I want to sample an audio signal. I have a wav file 5 seconds long. I want save samples every 300 ms.
I use function audioread in MATLAB that read samples containing in file, this is my code:
[signal,fs]=audioread('file.wav');
dt = 1/fs;
N = length(signal);
t = 0:dt:(N-1)*dt;
plot(t,signal)
ms=t*1000;
How can I do save in an array samples that are repeated every 300 ms?
Let's assume your wav file has a sampling rate of fs = 44100 (which is quite common), i.e. you have 44100 samples per second. Now, you want to have one sample each 0.3 s. You have to calculate the corresponding number of samples to "skip" with respect to your original sampling rate, i.e. skip = 0.3 * fs = 13230 in this case. Now, you can simply access each skip'th element in your original signal (and also time interval t).
Here's some code to do the work, and visualize the above:
% Artificial data
signal = sin(linspace(0, 2*pi, 5 * 44100));
fs = 44100;
dt = 1 / fs;
N = length(signal);
t = 0:dt:(N-1)*dt;
% "Re-sampling" parameters
dt_new = 0.3;
skip = dt_new * fs;
% Extract every skip'th value from original time interval and signal
t_new = t(1:skip:end).'
signal_new = signal(1:skip:end);
% Some visualization
figure(1);
hold on;
plot(t, signal);
plot(t_new, signal_new, 'r.', 'MarkerSize', 15);
hold off;
We get the following output, the original signal is blue, the red points are the samples at every 0.3 s:
If you have a look at t_new, you see, that the sampling points exactly match your desired interval of 0.3 s:
t_new =
0.00000
0.30000
0.60000
0.90000
1.20000
1.50000
1.80000
2.10000
2.40000
2.70000
3.00000
3.30000
3.60000
3.90000
4.20000
4.50000
4.80000
Hope that helps!
EDIT: There's also a resample function available in the Signal Processing Toolbox. I'm not sure, if this function is useful here, since the new sampling rate would be fs_new = 1 / 0.3 = 3.3333, but resample only accepts integers. Maybe, there's another more sophisticated (toolbox) function to do the job automatically.

Inverse Fourier of a Discrete and Finite Sampling Window

I am trying to find the inverse Fourier of a discrete sampling window with N_f = 11 elements. I am expecting to see a periodic Sinc-like signal in the time-domain:
However, this is the output I get:
Why the number of observed oscillations in my output is more than the expected output?
N_f = 11; % Number of samples in the finite sampling window in Frequency domain
delta_f = 1;
f = [-N_f/2+1:delta_f:N_f/2];
wf = ones(1, N_f)/N_f; % W(f):finite sampling window in Frequency Domain
N_t =128;
wt = ifftshift(ifft(wf, N_t))*N_t; % w(t):Inverse Fourier of the window
I think one of the issues with your code is related to the location of the origin. You create an array wf with 11 ones (and normalized), then call ifft(wf,128). This pads the array with zeros to a size of 128, but the 11 ones are on the left side. You can see this by doing
fft(ifft(wf, N_t))
Thus, your window is shifted by 5 samples to the right, covering frequency bins 0 through 11, rather than -5 through 5 (or identically, 0 through 5 and 124 through 128).
The code below creates a signal with 128 samples, and fills the 11 frequency bins around the middle with 1/11. By calling ifftshift we rotate the signal such that the middle element is moved to the leftmost bin. Now bins 0 through 5 and 124 through 128 are non-zero. I then call ifft, and fftshift to move the 0 frequency back to the middle of the signal. Finally, I plot three repetitions of this signal.
N_f = 11; % Number of samples in the finite sampling window in Frequency domain
N_t = 128;
wf = zeros(1,N_t);
wf( N_t/2 - floor(N_f/2) + 1 : N_t/2 + floor(N_f/2) + 1 ) = 1 / N_f;
wt = fftshift(ifft(ifftshift(wf))) * N_t;
figure; plot(repmat(wt,1,3))
As you can see, the result is as you expected it. Note that the wt result of ifft is actually real-valued. The result of your inverse transform wasn't real-valued, you had to ignore the imaginary component to produce your plot. That's a sign that the input signal wasn't symmetric!
We can change N_f to be twice as large, yielding a result similar to yours, but with a purely real output:
N_f = 21;
N_t = 128;
wf = zeros(1,N_t);
wf( N_t/2 - floor(N_f/2) + 1 : N_t/2 + floor(N_f/2) + 1 ) = 1 / N_f;
wt = fftshift(ifft(ifftshift(wf))) * N_t;
figure; plot(repmat(wt,1,3))

histogram in matlab but without using hist function

I'm a little bit stuck on how to plot a histogram in MatLab without using hist function
the question is that
Generate a random number between (0 ,100) and plot 1000 of those random digits on xy,plan as histogram
example
let interval is 10
x | y
0 -10 | 5
10-20 | 9
20-30 | 15
etc ...
where x is interval and y represent the repeated random number in that interval
I try to write this code
function []=drawhist(a,b)
x=a+(b-a)*rand(1,1000);
bar(x)
end
but not give me the output desired , please help me with any idea to understand how to write this function
This should do what you want, however this is for integers.
If you want this to generalise to flots you need to define the accuracy of sampling and define edges that are half that accuracy
function [centers,freq] = drawhist(range,interval,density)
% example
% generate 1000 random integers ranging between 0 and 100;
% drawhist([0,100],10,1000);
V = randi([0,100],density,1);
min_x = range(1); max_x = range(2);
bin = linspace(min_x,max_x,interval+1);
freq = zeros(interval,1);
for ii=1:interval
freq(ii) = sum(V>bin(ii)&V<bin(ii+1));
end
centers = bin(2:end)-(bin(2:end)-bin(1:end-1))/2;
bar(centers,freq);
end
Enjoy

Matlab:Interpolation Error

I would like to perform a frame based analysis on the following curve Which expresses the relation between time and concentration (x-axis: time in minutes; y-axis: concentration in Mbq):
For the above curve I would like to perform frame based sampling by splitting the curve into 19 frames:
19 frames:
4 frames : Each of 15 seconds time interval
2 frames : Each of 30 seconds time interval
2 frames : Each of 60 seconds time interval
11 frames : Each of 200 seconds time interval
I have written the following interpolation function for the frame analysis. c_t is where my signal which was expressed in the figure above is stored:
function c_i = Frame_analysis(a1,a2,a3,b1,b2,b3,td,tmax,k1,k2,k3)
t= 0:6:3000; % The original sample time, in seconds
t_i =[0:15:60,90:30:120,180:60:240,440:200:2240];% The interpolated sample time for first 4 frames of 15 second interval
K_1 = (k1*k2)/(k2+k3);
K_2 = (k1*k3)/(k2+k3);
%DV_free= k1/(k2+k3);
c_t = zeros(size(t));
ind = (t > td) & (t < tmax);
c_t(ind)= conv(((t(ind) - td) ./ (tmax - td) * (a1 + a2 + a3)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
% Y_i = interp1(t,c_t(ind), t_i); % Interpolation for first frame
ind = (t >= tmax);
c_t(ind)=conv((a1 * exp(-b1 * (t(ind) - tmax))+ a2 * exp(-b2 * (t(ind) - tmax))) + a3 * exp(-b3 * (t(ind) - tmax)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
c_i = interp1(c_t(ind),t_i);% Interpolation for Next consequtive frames
figure;
plot(t_i,c_i);
axis([0 3000 -2000 80000]);
xlabel('Time[secs]');
ylabel('concentration [Mbq]');
title('My signal');
%plot(t,c_tnp);
end
When I run the code, I have obtained a curve without any interpolation as you can see from figure expressed below:
Where have I made a mistake in my code and how can I possibly perform a better interpolation for obtaining different frames in my Output curve expressed in first figure?
Following are the input values which i have provided manually
Frame_analysis(2501,18500,65000,0.5,0.7,0.3,3,8,0.014,0.051,0.07)
There are multiple issues here, and it will be up to you to decide how to address them.
This is what I can provide:
You do not specify an x-coordinate for your plot command. That can be done, however, Matlab will use the index of the vector for the x-axis. Example: if you have
y = 1:2:6;
plot(y);
hold on;
y = 1:1:6;
plot(y);
you'll see the difference.
How does this apply to your case? You specify a vector of higher resolution (t_i, compared to t), but in your plot command you do not provide this new vector for the x-coordinate.
Your definition of c_t provides very very small values (on the order of 10^-77). And from t > 60, your output is indifferent from 0.
How does that effect your interpolation?
You specify that for the interval [0 60] you want step-sizes of 15 - that does not give you a lot of resolution:
You might want to change to something like:
t_i =[0:0.5:60,90:30:120,180:60:240,440:200:2240];
Which will give you this plot:
In either case, I do not understand why you chose a data range above 60 (all the way until 3000) for the data you are trying to plot. This explains why you do not see anything with your axis limits axis([0 3000 -2000 80000]); that by far exceed the range of y-values and obscures the non-zero data entries for small x.