I measure the impulse response of a microphone. At beginning of plot i have some delay and then highest value comes at 40 ms and decreases till 45 ms.
When I take fourier transform, I only want to use the part between 35-45 ms. when I use different microphones, delay decreases or increases so the peak value is shifting. So, the time range I want also changes. How I can get that range, which contains highest value, automaticaly in MATLAB?
Assuming you have a vector y of measurements and want an interval of length 2r+1 measurements you could do:
center = find(y==max(y)); % find the peak value
y_edited = y(center-r:center+r); % look at r samples before and after this peak
Then perform the fourier transform on y_edited. Note that having noise on your signal might affect your performance.
Related
As above lets Fs is sampling frequency, L is signal's length and t is time range.
As using mdwtdec in Matlab in order to decompose multi-raw signal into specific frequency band, I just notice that decomposed signal's length at 1st level is split into half, and keep slit into half of 1st level signal at 2nd level.
Raw signal's time range calculation: t = 0 --> (L/Fs)
My question is in every decomposition level the Sampling frequency Fs is still the same? and at every decomposition level how I can calculate the time range of each Detail and Approximation coefficient.
Also as verify the frequency band of Discrete Wavelet Transform I applied FFT at each level following this post: https://jp.mathworks.com/help/matlab/ref/fft.html?lang=en
According to this post my first question need to be answered.
Thank you very much.
I'm pretty positive that in discrete wavelet transform, the time series data or signals, if we wish, would be downsampled by a factor of 2, which means that if we would be having 2^10 or 1024 datapoints in our original time series data, in the first level, it would be divided into 2 and our level one sampling frequency would be 2^9 or 512, in second level would decrease to 256, and so on.
However, in continuous wavelet transform, it would most likely remain the same.
Based on the references, I copy some codes here that you might want to test and see, you might want to reduce the number of levels and Fs here and you can define your own x if you wish:
Fs = 1e6;
t = 0:1/Fs:1-1/Fs;
x = cos(2*pi*50*t);
[C,L] = wavedec(x,15,'db4');
details = detcoef(C,L,'cells');
d14recon = wrcoef('d',C,L,'db4',14);
plot(d14recon,'k');
d13recon = wrcoef('d',C,L,'db4',13);
hold on;
plot(d13recon,'r'); %look how small the amplitude is
a13recon = wrcoef('a',C,L,'db4',13);
plot(a13recon,'b');
Useful Links:
I'm not expert about it, you can likely read more about it and find out your desired information. There are also lots of YouTube videos about it.
Discrete wavelet transform relation to sampling frequency of the signal
Single-level discrete 2-D wavelet transform
Let's say that I have a signal in Matlab like this
x = cos(2*pi*10*t) + cos(2*pi*20*t) + cos(2*pi*50*t);
And I want to change the values between 20 and 30 hz into 0. How can I do that? I mean, those values generated from the x formula, I want to change them a little bit.
You can do it by performing FFT over x and setting to zero those values that are between 20 and 30 Hz then applying the FFT inverse on the previous values and you should get the signal without those frequencies. However, you may lose valuable information or the signal might just not look as you wish. Therefore, I recommend you to use a "Bandstop filter". The band stop filter will receive the cutoff frequencies (the limit frequencies you want to work with) and some other parameters. The bandstop filter basically removes from the signal the frequencies that you specify. And the good part is that it can be done as easy as doing what follows:
First you have to build the filter. To do so, you need to indicate the filter order which can be defined as you wish. Usually a second order works good. Also, you have to be aware of your sampling rate Fs.
d = designfilt('bandstopiir','FilterOrder',2, ...
'HalfPowerFrequency1',20,'HalfPowerFrequency2',30, ...
'SampleRate',Fs);
Now you only need to apply the filter to your desired signal.
filtered_signal_x = filtfilt(d, x)
Now, filtered_signal_x should not have the frequencies you wanted to delete. By using the bandstop you don't have to mess with the FFT and that kind of stuff and is a way faster so I think its the best option.
You can either use a filter, or you can filter it by yourself by going into Fourier space and explicitly setting the signal on the frequencies you need to zero. After that, you need to go back to the time domain. Here is a code:
t=0:0.01:0.99; % time
x = cos(2*pi*10*t) + cos(2*pi*20*t) + cos(2*pi*50*t); %signal
xf=fftshift(fft(x)); %Fourier signal
N=size(x,2); % Size of the signal
frequency=2*pi*[-N/2:N/2-1]; %frequency range
frequencyrangeplus=find(frequency/(2*pi)>=20 & frequency/(2*pi)<=30); %find positive frequencies in the required range
frequencyrangeminus=find(frequency/(2*pi)<=-20 & frequency/(2*pi)>=-30); %find negative frequencies in the required range
xf(frequencyrangeplus)=0; %set signal to zero at positive frequencies range
xf(frequencyrangeminus)=0; %set signal to zero at nagative frequencies range
xnew=ifft(ifftshift(xf)); %get the new signal in time domain
xcheck= cos(2*pi*10*t) + cos(2*pi*50*t); % to check the code
max(abs(xcheck-xnew)) % maximum difference
I use the matlab software. To my question.
I have a audio signal, on which i am applying a STFT. I take a segment
(46 ms, specifially chosen) out of my signal y(audio signal) and use a FFT on it. Then i go to the next segment, until to end of my audio signal.
My WAV-File is 10.8526 seconds long. If I have a sample frequency of
44100Hz, this means my y is 10.8526*fs = 478599.66 which is
shown in the workspace as 478 6000 x2 double.
The length of my fft is 2048. My signal are differentiated under lower frequency band [0 300], mfb [301 5000] and hfb [5001 22050(fs/2)].
The bands are just an example and not the actual matlab code. Basicall what i want (or what I am trying to do), is to get the values of my bins in the defined frequency band and do a arithmetic mean on it.
I chose 46 ms because, I want it as long as the fft length, or nearly as long as the fft. (It is not exact).Afterwards, I want to try plotting it, but that is not important right now. Any help is appreciated.
Fourier transform of a signal in time domain in a vector of size n will return another vector of size n of same signal but in frequency domain.
Frequency domain will be from 0 (dc offset) to your sampling frequency. But you will only be able to use half of that. Second half would have same values but mirrored.
You can obtain the center frequency of each useful bin with:
f = Fs*(0:(n/2))/n;
I have a signal that more or less repeats itself (not exactly the same from one to the next, see plot to the left). If I use autocorrelation I get a number of maximums (right plot), but it doesn't tell me where (which sample number) the correlation is high. It gives me the lags but I lose information on the position, that is, the sample number in my original data where the signal occurs. For example in the auto-corr. plot, the second peak at sample 500 should correspond to the signal at about sample 750 in the data plot. I could do this by using a small window that moves over the data trace and find the maximums but it takes too much time. Is there a faster way of doing this in matlab? thanks.
I think you're misinterpreting autocorrelation. The correlation peak at 5000 is not due to a single location in the time series, but rather to the fact that the entire time series is similar to itself, when offset by 5000 samples. As much of that peak is due to the time series peak at 18000 as it is to the time series peak at 7500. Your autocorrelation will get very strange if, for example, you do not have a truly periodic time series (that is, if the interval between pulses is nonuniform).
If you can isolate one example of your pulse, and choose the location you want as your t=0, then a correlation of that one pulse with the time series will give you just what you want. Each pulse will light up clearly, at the time location at which it occurs. Then you just need a peak finder.
Yes, you could get the indices of the elements with the maximum amplitude using
treshold = max(a)/2
ind = find(a>=treshold)
where a is the matrix containing the correlation result.
I have data from a model I am running. However the data is collected at each time step and there are varying numbers of time steps. It works out that although there are varying time steps, it is compensated by the change in time step so that all runs are running for the same time.
However I would think that when I have a vector that is 200 in length and one that is 900 in length, taking the FFT will give me inherently different frequencies. I feel like I should take the FFT with respect to the same time axis of all the samples.
The way I have the data now is just as row vectors were each entry is not associated with a space in time.
Is there a way to take the fft of each vector with respect to their place in a time axis rather than their place in the vector array?
My goal is to write a for loop and take the fft of many data sets, and then plot them to compare of frequency signatures change.
If you collect 200 samples in 1 second (200 Hz), you can resolve input data from 1 Hz (1/(1 sec)) to 100 Hz. If you sample for 1 second collecting 900 samples, you can resolve input from 1 Hz to 450 Hz. So both your samples have the same spacing (sampling in the frequency axis is 1 Hz), but they go up to different maximum frequencies!
If your issue is just about plotting, you can either throw away the high frequencies which are not available in all your plots:
totaltime=1; %# common total time of all datasets, in seconds
minsamplenumber=200;
figure;
hold all;
cutofffreq=((minsamplenumber/2+1)/totaltime);
freqscale=0:(1/totaltime):cutofffreq;
datasetcount=42;
ffts=NaN(minsamplenumber,datasetcount);
for i=1:datasetcount
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts(:,i)=fft(data{i},minsamplenumber);
plot(freqscale,ffts{i}(1:end/2+1));
end
... or live with reality, and plot all data you have:
totaltime=1; %# common total time of all datasets, in seconds
figure;
hold all;
for i=1:42
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts{i}=fft(data{i});
maxfreq(i)=((numel(ffts{i})/2+1)/totaltime);
freqscale{i}=0:(1/totaltime):maxfreq(i);
plot(freqscale{i},ffts{i}(1:end/2+1));
end
You could resample your data (by filtered interpolation) into constant length vectors where the sample rate was the same constant rate in each frame. You may have to overlap your FFT frames as well to get constant frame or window offsets.