How to convert time bins in spectrogram to real time? - signal-processing

I have an output of a spectrogram with the shape of (8193, 2110). This means that I have 2110 time frames and 8193 frequency bins. I want to convert time bins to real time. This spectrogram is related to a one day long file, so instead on time frame I need the exact real time like : 12:32:45.

A single FFT in your spectrogram represents a time window of duration T = N / Fs, where N = FFT size and Fs = sample rate. If you have no overlap between successive FFTs then the i’th FFT represents a time window of duration T, starting at time i*T.
If you have overlap between successive FFTs, e.g. k = 0.5 (50% overlap), then i*T obviously becomes (1-k)*i*T.

Related

Strange FFT spectrum from a near perfect sinusoid

I have retrieved some signal in my Abaqus simulation for verification purpose. The true signal shall be a perfect sinusoid at 300kHz and I performed fft on the sampled signal using scipy.fftpack.fft.
But I got a strange spectrum as shown below (sorry that I am too lazy to scale the x-axis of the spectrum to the correct frequency). In the same figure, I sliced the signal into pieces and plotted in the time domain. I also repeated the same process for a pure sine wave.
This totally surprises me. As indicated below in the code, sampling frequency is 16.66x of the frequency of the signal. At the moment, I think it is due to the very little error in the sampling period. In theory, Abaqus shall sample it in a regular time interval. As you can see, there is some little error so that the dots in my signal appear to be thicker than the perfect signal. But does such a small error give a striking difference in the frequency spectrum? Otherwise, why is the frequency spectrum like that?
FYI1: This is the magnified fft spectrum of my signal:
FYI2: This is the python code that was used to produce the above figures
def myfft(x, k, label):
plt.plot(np.abs(fft(x))[0:k], label = label)
plt.legend()
plt.subplot(4,1,1)
for i in range(149800//200):
plt.plot(mysignal[200*i:200*(i+1)], 'bo')
plt.subplot(4,1,2)
myfft(mysignal,150000//2, 'fft of my signal')
plt.subplot(4,1,3)
[Fs,f, sample] = [5e6,300000, 150000]
x = np.arange(sample)
y = np.sin(2 * np.pi * f * x / Fs)
for i in range(149800//200):
plt.plot(y[200*i:200*(i+1)], 'bo')
plt.subplot(4,1,4)
myfft(y,150000//2, 'fft of a perfect signal')
plt.subplots_adjust(top = 2, right = 2)
FYI3: Here is my signal in .npy and .txt format. The signal is pretty long. It has 150001 points. The .txt one is the raw file from Abaqus. The .npy format is what I used to produce the above plot - (1) the time vector is removed and (2) the data is in half precision and normalized.
Any standard FFT algorithm you use operates on the assumption that the signal you provide is uniformly sampled. Uniform in this context means equally spaced in time. Your signal is clearly not uniformly sampled, therefore the FFT does not "see" a perfect sine but a distorted version. As a consequence you see all these additional spectral components the FFT computes to map your distorted signal to the frequency domain. You have two options now. Resample your signal i.e. it is uniformly sampled and use your off the shelf FFT or take a non-uniform FFT to get your spectrum. Here is one library you could use to calculate your non-uniform FFT.

Calculating PSD of signal in GNURadio

My general aim is to calculate the power spectral density of an input signal exactly as what is seen in the QT GUI Frequency Sink block. I'll need to process the PSD values later on. Here is my current setup.
These graphs are produced when a signal (no transmission) is inputted.
Blue = signal, green = max of signal, pink = min of signal.
My implementation of PSD produces a graph that has the same height and shape as the actual PSD shown by the QT GUI Frequency Sink block, but wrong offset - the actual PSD is about 66 dB lower than mine.
I eyeballed the rough max/min/signal y-axis values:
Actual PSD has max = -76dB, min = -115dB, signal = -86dB.
My PSD has max = -10dB, min = -50dB, signal = -20dB.
I'm not really sure what I'm doing wrong; the offset of -66dB seems pretty arbitrary and I think I'm on the right track generally.
You need to scale result of FFT by FFT length. 20Log10(2048) = 66 dB. You are estimating the PSD by calculating the Periodogram which is magnitude squared of the FFT divided by length of FFT.

Frequency Transform : Fundametal Concept

I was going thru this book to understand wavelets. Its a beautifully written not much technical document.
web.iitd.ac.in/~sumeet/WaveletTutorial.pdf
But in its very first chapter it describes below figure with explanation:
The frequency is measured in cycles/second, or with a more common
name, in "Hertz". For example the electric power we use in our daily
life in the US is 60 Hz (50 Hz elsewhere in the world). This means
that if you try to plot the electric current, it will be a sine wave
passing through the same point 50 times in 1 second. Now, look at the
following figures. The first one is a sine wave at 3 Hz, the second
one at 10 Hz, and the third one at 50 Hz. Compare them
But I am unable to understand what X and Y axis values represents. The X values range is in between [1,-1] so I am assuming it is value of the signal while Y axis is representing the time in milliseconds (1000ms = 1 sec). But then the document goes on further to state the representation of same signal in frequency-amplitude domain:
So how do we measure frequency, or how do we find the frequency
content of a signal? The answer is FOURIER TRANSFORM (FT). If the FT
of a signal in time domain is taken, the frequency-amplitude
representation of that signal is obtained. In other words, we now have
a plot with one axis being the frequency and the other being the
amplitude. This plot tells us how much of each frequency exists in our
signal.
But I am not able to understand what does in the upper graph X and Y axis values represents - shouldn't is be Frequency (X Axis) and Amplitude (Y axis) - if I am correct then why does Y axis has values ranked as 0,200 and 400 - shouldn't it be between range [1,-1] or rather [0,1]?
For the time domain signals the X axis is time and the Y axis is amplitude.
For the frequency domain equivalents the X axis is frequency and the Y axis is magnitude.
Note that when using most FFTs there is a scaling factor of N, where N is the number of points, so the magnitude values in the frequency domain plots are much greater than amplitude of the original time domain signal.
As Paul R wrote above, in the first image the horizontal X-axis represents time with the units ms.
The time interval has the length 1000ms.
The vertical Y-axis represents the amplitude of the signal. However, in the diagram the unit is not Volt, but it is normalized to amplitude 1.
If you perform a Fourier Transformation on that time signal, you will get a frequency spectrum.
If you use a DFT (Discrete Fourier Transformation) or a FFT (Fast Fourier Transformation),
the result depends on the implementation of the algorithm.
a) If the algorithm delivers a normalized result, the amplitude of your frequency line is 0.5 (if the amplitude of your input signal is 1).
b) If the algorithm delivers a non normalized result, the amplitude of your frequency line is half the value of the number of DFT/FFT input values.
Your frequency line has the value of 500, which means the algorithm does not use normalization and the number of input samples was 1000.
Now, what is represented by the horizontal X-axes in the frequency domain?
In the time domain, the length of your time input interval is T = 1000ms = 1s.
Therefore the distance between the frequency lines in the frequency domain is df = 1/s = 1Hz.
As we know from the amplitude in the frequency domain, the input signal in time domain had 1000 samples. This means the sampling time was dt = T/1000 = 1s/1000 = 1ms.
Therefore the total frequency interval F = (fmin, ..., fmax) in frequency domain is 1/dt = 1/1ms = 1kHz.
However, the range does NOT start at fmin = 0 Hz and ends at 1kHz, as one could assume inspecting the upper diagram in the second image. The spectrum calculated by a DFT/FFT contains a positive and a negative frequency range. This means you get a frequency range: (-500Hz, -499Hz, -498Hz, ... -1Hz, 0Hz, 1Hz, 2Hz, ..., 498Hz, 499Hz). The value 500Hz does not exist!
However, for the user's convenience the spectrum is not output in this order, but it is shifted by 500Hz (F/2). This means the spectrum starts with the DC value:
0Hz, 1Hz, 2Hz, ..., 498Hz, 499Hz, -500Hz, -499Hz, -498Hz, ..., -2Hz, -1HZ.
Because the spectrum of a real input function is hermitian Y(f) == Y(-f)*, the positive band carries the complete information. So, you can cut off the negative side band.
The upper diagram in the second image shows two peaks. The first peak appears at f = 50Hz and the second peak is shown at f=950Hz. However, this is not correct. The labels of the horizontal axes are wrong. The second peak appears at f = -50Hz.
In the lower diagram the frequency range ends at 500Hz (499Hz would be correct)a). The range of the negative frequencies is cut off.

Cepstrum analysis: how to find quefrency step?

I'm newbie in cepstrum analysis. So that's the question.
I have signal with the length 4096 and sample rate 8000 Hz. I make FFT and get the array with the length 4096*2 (2*i position is for cosinus coeff, 2*i+1 position is for sinus coeff). Frequency step is (sampleRate/signalLength == 8000/4096). So, I can calculate frequency at i position this way: i*sampleRate/signalLength.
Then, I make the cepstrum transformation. I can't understand how to find quefrency step and how to find frequency for given quefrency.
The bin number of an FFT result is inversely proportional to the length of the period of a sinusoidal component in the time domain. The bin number of a quefrency result is also inversely proportional to the distance between partials in a series of overtones in the frequency domain (this distance often the same as a root or fundamental pitch). Thus quefrency bin number would be proportional to period or repeat lag (autocorrelation peak) of a harmonically rich periodic signal in the time domain.

Frequency Shifting with FFT

I've been experimenting with a few different techniques that I can find for a freq shifting (specifically I want to shift high freq signals to a lower freq). At the moment I'm trying to use this technique -
take the original signal, x(t), multiply it by: cos(2 PI dF t), sin(2
PI dF t)
R(t) = x(t) cos(2 PI dF t)
I(t) = x(t) sin(2 PI dF t)
where dF is the delta frequency to be shifted.
Now you have two time series signals: R(t) and I(t).
Conduct complex Fourier transform using R(t) as real and I(t) as
imaginary parts. The results will be frequency shifted spectrum.
I have interpreted this into the following code -
for(j=0;j<(BUFFERSIZE/2);j++)
{
Partfunc = (((double)j)/2048);
PreFFTShift[j+x] = PingData[j]*(cos(2*M_PI*Shift*(Partfunc)));
PreFFTShift[j+1+x] = PingData[j]*(sin(2*M_PI*Shift*(Partfunc)));
x++;
}
//INITIALIZE FFT
status = arm_cfft_radix4_init_f32(&S, fftSize, ifftFlag, doBitReverse);
//FFT on FFTData
arm_cfft_radix4_f32(&S, PreFFTShift);
This builds me an array with interleaved real and imag data and then FFT. I then inverse the FFT, but the output im getting is pretty garbled. Results seem huge in comparison to what I think they should be, and although there are a few traces of a freq shifted signal, its hard to tell as the result seems mostly pretty noisy.
I've also attempted simply revolving the array values of a standard FFT of my original signal to get a freq shift, but to no avail. Is there a better method for doing this?
have you tried something like:
Use a Hanning window for each framed data
Once you have your windowed frame of audio data, you do an FFT on it
Do some kind of transformation in the frequency domain (you can use
Flanagan - phase vocoder)
Now you need to go back to the time domain with an IFFT
Apply Hanning window in the IFFT data
Use overlap-add at each new frame of time-domain data into the output
stream
My results:
I created two concatenated sinusoids (250Hz and 400Hz) and move one octave UP!
Blue waveform is the original and red was changed, you can see one fadeIN-fadeOut caused by overlap add and hann window !
If you want the frequency shift to sound more "natural", you will have to maintain the ratios between all the initial frequency bins, where the amount of shift will depend on the FFT bin, thus requiring lots of interpolation. The Phase Vocoder algorithm will use multiple FFTs to reduce phase distortion in the result.

Resources