FFT on accelerometer data spike at 0 - matlab

I have some accelerometer data in MATLAB and I was told to try FFT and try to use FFT features on classification. However, I am confused about the plot after FFT. It seems that there is a large spike only in the beginning of the plot and I am not sure what to make of it. I tried using some code from other posts such as this one: Accelerometer with FFT - strange output, and also some examples on the Mathworks website, but it did not help.
data = acc_data_x(1:300);
fs = 1/(1/12);
m = length(data);
nfft = 2^nextpow2(m);
y = fft(data,nfft)/m;
f = fs/2 * linspace(0,1,nfft/2+1);
power = abs(y);
plot(f,power(1:nfft/2+1))
t = (0 : m-1)/fs;
figure
plot(t,data);
I attached the plot of the accelerometer data in x and the result of the FFT. Is there some other step I am missing? I apologize for any ignorance since this is my first time trying FFT and working with this type of data.
Accelerometer Data in X plot:
After FFT:
Edit: I have tried Gareth's suggestion and used detrend function in MATLAB
After Detrend and FFT:
Also here is the full data with FFT (in the first example I only used up to 300 data points).
I'm now confused if this tells me any information?

You should first detrend your data. FFT inputs that have an uncorrected DC bias (ie, sits positive or negative) have a strong 0 Hz component.
Try data = detrend(data) after your first line. It'll skew some of the other things you do, but might help with showing the issue in the FFT. You can more carefully manage your data so that you can both clean it for FFT and also plot the original raw data once you feel happy with the issue being mostly fixed.

The amplitude of the first "zero-frequency" component in FFT is exactly the mean value of your data. If you fft(x-mean(x)), the first component will be zero. Other components nearby can be related with slow trend.

Related

How to recreate an instrument sound from a .WAV file by using FFT and findpeaks() in MATLAB?

I want to generate my own samples of a Kick, Clap, Snare and Hi-Hat sounds in MATLAB based on a sample I have in .WAV format.
Right now it does not sound at all correct, and I was wondering if my code does not make sense? Or if it is that I am missing some sound theory.
Here is my code right now.
[y,fs]=audioread('cp01.wav');
Length_audio=length(y);
df=fs/Length_audio;
frequency_audio=-fs/2:df:fs/2-df;
frequency_audio = frequency_audio/(fs/2); //Normalize the frequency
figure
FFT_audio_in=fftshift(fft(y))/length(fft(y));
plot(frequency_audio,abs(FFT_audio_in));
The original plot of y.
My FFT of y
I am using the findpeaks() function to find the peaks of the FFT with amplitude greater than 0.001.
[pk, loc] = findpeaks(abs(FFT_audio_in), 'MinPeakHeight', 0.001);
I then find the corresponding normalized frequencies from the frequency audio (positive ones) and the corresponding peak.
loc = frequency_audio(loc);
loc = loc(length(loc)/2+1:length(loc))
pk = pk(length(pk)/2+1:length(pk))
So the one sided, normalized FFT looks like this.
Since it looks like the FFT, I think I should be able to recreate the sound by summing up sinusoids with the correct amplitude and frequency. Since the clap sound had 21166 data points I use this for the for loop.
for i=1:21116
clap(i) = 0;
for j = 1:length(loc);
clap(i) = bass(i) + pk(j)*sin(loc(j)*i);
end
end
But this results in the following sound, which is nowhere near the original sound.
What should I do differently?
You are taking the FFT of the entire time-period of the sample, and then generating stationary sinewaves for the whole duration. This means that the temporal signature of the drum is gone. And the temporal signature is the most characteristic of percussive unvoiced instruments.
Since this is so critical, I suggest you start there first instead of with the frequency content.
The temporal signature can be approximated by the envelope of the signal. MATLAB has a convenient function for this called envelope. Use that to extract the envelope of your sample.
Then generate some white-noise and multiply the noise by the envelope to re-create a very simple version of your percussion instrument. You should hear a clear difference between Kick, Clap, Snare and Hi-Hat, though it won't sound the same as the original.
Once this is working, you can attempt to incorporate frequency information. I recommend taking the STFT to get a spectrogram of the sound, so you can see how it the frequency spectrum changes over time.

How to generate smooth filtered envelope on EMG data in Matlab

I'm new to analysing EMG data and would appreciate some carefully explained help.
I would like to generate a smooth, linear enevelope signal of my EMG data (50kHz sampling rate) like the one published in this paper: https://openi.nlm.nih.gov/detailedresult.php?img=PMC3480942_1743-0003-9-29-3&req=4
My end goal is to be able to analyze the relationship between EMG activity (output) and action potentials fired from upstream neurons (putative input) recorded at the same time.
Even though this paper lists the filtering methods out quite clearly, I do not understand what they mean or how to perform them in matlab, which is the analysis tool I have available to me.
In the code I have written so far, I can dc offset as well as rectify my data:
x = EMGtime_data
y = EMGvoltage_data
%dc offset
y2=detrend(y)
% Rectification of the EMG signal
rec_y=abs(y2);
plot(x, rec_y)
But then I am not sure how to proceed.
I have tried the envelope function, but it is not as smooth as I would like:
For instance, if I used the following:
envelope(y_rec,2000,'rms')
I get this (which also doesn't seem to care that the data is rectified):
Even if I were to accept the envelope function, I'm not sure how to access just the processed envelope data to adjust the plot (i.e. change the y-range), or analyse the data further for on-set and off-set of the signal since the results of this function seem to be coupled with the original trace.
I have also come across fastrms.m, which seems promising. Unfortunately, I do not understand how to implement this function since the general explanation is over my head and the example code is lacking any defined variable (so I don't know where to integrate my own data!)
The example code from fastrms.m file exchange is here
Fs = 200; T = 5; N = T*Fs; t = linspace(0,T,N);
noise = randn(N,1);
[a,b] = butter(5, [9 12]/(Fs/2));
x = filtfilt(a,b,noise);
window = gausswin(0.25*Fs);
rms = fastrms(x,window,[],1);
plot(t,x,t,rms*[1 -1],'LineWidth',2);
xlabel('Time (sec)'); ylabel('Signal')
title('Instantaneous amplitude via RMS')
I will be eternally grateful for help in understanding how to filter and smooth EMG data!
In order to analysis EMG signals in time domain, researcher use The combination of rectification and low pass filtering which is also called finding the “linear envelope” of the signal.
And as mentioned in both the above sentence and your attached article image's explanation, in order to plot overlaid signal, you could simply low pass filter your signal at specific frequency.
In your attached article the said signal was filtered at 8 HZ.
For better understanding the art of EMG signal analysis , i think this document could help you a lot (link)

Summing Frequency Spectrums

I've a set of data from an EEG device from which I want to find the strength of different brain waves in Matlab. I tried to use EEGLAB but I wasn't really sure how, so at this point I'm simply using the dsp toolbox in Matlab.
For background: I've 15 epochs, 4 seconds in length. The device sampled at 256 Hz, and there are 264 sensors, so there are 1024 data points for each sensor for each epoch, i.e. my raw data is 264 x 1024 x 15. The baseline is removed. The data in each epoch is going to be used to train a classifier eventually, so I'm dealing with each epoch individually. I'll come up with more data samples later.
Anyways, what I've done so far is apply a Hann filter to the data and then run fft on the filtered data. So now I have the information in frequency domain. However, I'm not quite sure how to go from the power of the fft buckets to the power of certain frequency bands (e.g. alpha 8-13), to get the values I seek.
I know the answer should be straightforward but I can't seem to get find the answer I want online, and then there's further confusion by certain sources recommending using a wavelet transform? Here's the little bit of code I have so far, the input "data" is one epoch, i.e. 264 x 1024.
% apply a hann window
siz = size(data);
hann_window = hann(siz(2));
hann_window = repmat(hann_window.', siz(1), 1);
hann_data = data.' * hann_window;
% run fft
X = fft(hann_data, [], 2);
X_mag = abs(X);
X_mag = X_mag.';
Thanks for the assistance!
If I'm understanding your question correctly, you are wanting to scale the FFT output to get the correct power. To do this you need to divide by the number of samples used for the FFT.
X_mag = abs(X)/length(hann_data); % This gives the correct power.
See this question for more info.
Once the content is scaled correctly, you can find the power in a band (e.g. 8 - 13 Hz) by integrating the content from the start to the stop of the band. Since you are dealing with discrete values it is a discrete integration. For perspective, this is equivalent to changing the resolution bandwidth of a spectrum analyzer.

the Length of signal in calculating FFT

I want to ask some questions related to the last question of mine so I don't want to post in another thread. My question contains a code, I therefore can't post it as a comment. So I have to edit my old question into a new one. Please take a look and help. Thank you.
I'm new to FFT and DSP and I want to ask you some questions about calculating FFT in Matlab. The following code is from Matlab help, I just removed the noise.
Can I choose the length of signal L different from NFFT?
I'm not sure if I used window correctly. But when I use window (hanning in the following code), I can't get the exact values of amplitudes?
When L and NFFT get different values, then the values of amplitudes were different too. How can I get the exact value of amplitude of input signal? (in the following code, I used a already known signal to check if the code work correctly. But in case, I got the signal from a sensor and I dont know ahead its amplitude, how can I check?)
I thank you very much and look forward to hearing from you :)
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 512; % Length of signal
NFFT=1024; % number of fft points
t = (0:L-1)*T; % Time vector
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t); input signal
X = fft(hann(L).*x', NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(X(1:NFFT/2+1))) % Plot single-sided amplitude spectrum.
L is the number of samples in your input signal. If L < NFFT then the difference is zero-padded.
I would recommend you do some reading on the effect of zero-padding on FFTs. Typically it is best to use L = NFFT as this will give you the best representation of your data.
An excepted answer on the use of zero-padding and FFTs is given here:
https://dsp.stackexchange.com/questions/741/why-should-i-zero-pad-a-signal-before-taking-the-fourier-transform
In your experiment you are seeing different amplitudes because you will have different amount of spectral leakage with each different L.
You need to apply a window function prior to the FFT to get consistent results with frequency components that have non-integral number of periods within your sampling window.
You might also want to consider using periodogram instead of using the FFT directly - it takes care of window functions and a lot of the other housekeeping for you.

matlab FFT. Stuck understanding relationship between frequency and result

We're trying to analyse flow around circular cylinder and we have a set of Cp values that we got from wind tunnel experiment. Initially, we started off with a sample frequency of 20 Hz and tried to find the frequency of vortex shedding using FFT in matlab. We got a frequency of around 7 Hz. Next, we did the same experiment, but the only thing we changed was the sampling frequency- from 20 Hz to 200 Hz. We got the frequency of the vortex shedding to be around 70 Hz (this is where the peak is located in the graph). The graph doesn't change regardless of the Cp data that we enter. The only time the peak differs is when we change the sample frequency. It seems like the increase in the frequency of vortex shedding is proportional to the sample frequency and this doesn't seem to make sense at all. Any help regarding establishing a relation between sample frequency and vortex shedding frequency would be greatly appreaciated.
The problem you are seeing is related to "data aliasing" due to limitations of the FFT being able to detect frequencies higher than the Nyquist Frequency (half-the sampling frequency).
With data aliasing, a peak in real frequency will be centered around (real frequency modulo Nyquist frequency). In your 20 Hz sampling (assuming 70 Hz is the true frequency, that results in zero frequency which means you're not seeing the real information. One thing that can help you with this is to use FFT "windowing".
Another problem that you may be experiencing is related to noisy data generation via single-FFT measurement. It's better to take lots of data, use windowing with overlap, and make sure you have at least 5 FFTs which you average to find your result. As Steven Lowe mentioned, you should also sample at faster rates if possible. I would recommend sampling at the fastest rate your instruments can sample.
Lastly, I would recommend that you read some excerpts from Numerical Recipes in C (<-- link):
Section 12.0 -- Introduction to FFT
Section 12.1 (Discusses data aliasing)
Section 13.4 (Discusses FFT windowing)
You don't need to read the C source code -- just the explanations. Numerical Recipes for C has excellent condensed information on the subject.
If you have any more questions, leave them in the comments. I'll try to do my best in answering them.
Good luck!
this is probably not a programming problem, it sounds like an experiment-measurement problem
i think the sampling frequency has to be at least twice the rate of the oscillation frequency, otherwise you get artifacts; this might explain the difference. Note that the ratio of the FFT frequency to the sampling frequency is 0.35 in both cases. Can you repeat the experiment with higher sampling rates? I'm thinking that if this is a narrow cylinder in a strong wind, it may be vibrating/oscillating faster than the sampling rate can detect..
i hope this helps - there's a 97.6% probability that i don't know what i'm talking about ;-)
If it's not an aliasing problem, it sounds like you could be plotting the frequency response on a normalised frequency scale, which will change with sample frequency. Here's an example of a reasonably good way to plot a frequency response of a signal in Matlab:
Fs = 100;
Tmax = 10;
time = 0:1/Fs:Tmax;
omega = 2*pi*10; % 10 Hz
signal = 10*sin(omega*time) + rand(1,Tmax*Fs+1);
Nfft = 2^8;
[Pxx,freq] = pwelch(signal,Nfft,[],[],Fs)
plot(freq,Pxx)
Note that the sample frequency must be explicitly passed to the pwelch command in order to output the “real” frequency data. Otherwise, when you change the sample frequency the bin where the resonance occurs will seem to shift, which is similar to the problem you describe.
Methinks you need to do some serious reading on digital signal processing before you can even begin to understand all the nuances of the DFT (FFT). If I was you, I'd get grounded in it first with this great book:
Discrete-Time Signal Processing
If you want more of a mathematical treatment that will really expand your abilities,
Fourier Analysis by Körner
Take a look at this related question. While it was originally asked about asked about VB the responses are generically about FFTs
I tried using the frequency response code as above but it seems that I dont have the appropriate toolbox in Matlab. Is there any way to do the same thing without using fft command? So far, this is what I have:
% FFT Algorithm
Fs = 200; % Sampling frequency
T = 1/Fs; % Sample time
L = 65536; % Length of signal
t = (0:L-1)*T; % Time vector
y = data1; % Your CP values go in this vector
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2);
% Plot single-sided amplitude spectrum.
loglog(f,2*abs(Y(1:NFFT/2)))
title(' y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
I think there might be something wrong with the code I am using. I'm not sure what though.
A colleague of mine has written some nice GPL-licenced functions for spectral analysis:
http://www.mecheng.adelaide.edu.au/~pvl/octave/
(Update: this code is now part of one of the Octave modules:
http://octave.svn.sourceforge.net/viewvc/octave/trunk/octave-forge/main/signal/inst/.
But it might be tricky to extract just the pieces you need from there.)
They're written for both Matlab and Octave and serve mostly as a drop-in replacement for the analogous functions in the Signal Processing Toolbox. (So the code above should still work fine.)
It may help with your data analysis; better than rolling your own with fft and the like.