I have been reading the DSP Guide for what seems like a good 3 years now. Only until recently getting comfortable enough with programming did I decide to start experimenting around with FFT based convolution, 1D to be exact, one real in, a complex out.
I stumbled across some code for getting the FFT and IFFT and got it to work, I am getting a correct DFT in the complex frequency domain which after a little bit of bit manipulation (separating the complex array back into two separate real and imaginary arrays) and running it back through the IFFT followed by again more bit manipulation yeilds the original input like expected.
Now maybe I have the concept of Convolution all wrong but simply multiplying like elements of the complex arrays and then running the result back through the IFFT is giving bogus numbers. To test I am simply making a ramping kernel, and a dirac delta function as the input and plugging the result into the IFFT, the code is not giving the original kernel as expected.
public void convolution(double [] xReal, double [] xImag,
double [] hReal, double [] hImag){
for (int i = 0; i < n; i++){
xReal[i] *= hReal[i];
xImag[i] *= hImag[i];
}
}
My question is: is this code for multiplying the elements of the complex DFT correct.
I have been looking for simple convolution code or simply the math behind it but have had no such luck. Everything I have found has just been "multiplication in the frequency domain equals convolution in the time domain".
Multiplication in the frequency domain does a circular convolution, not a straight linear convolution, unless you zero pad out the FFTs and IFFT to longer than the sum of the length of the time domain signal and the full time domain impulse response. (Zero-pad, because a circular wrap/around of all zeros is the same as no wrap around).
Also, for convolution, you need to multiply by the transform (FFT) of the zero-padded impulse response (its frequency response), not the impulse response itself.
Also, the multiplication has to be a complex multiply, not a multiply of just the 2 separated component vectors.
Related
I'm trying to implement basic 2D vector math functions for a game, in Java. They will be intensively used by the game, so I want them to be as fast as possible.
I started with integers as the vector coordinates because the game needs nothing more precise for the coordinates, but for all calculations I still would have to change to double vectors to get a clear result (eg. intersection between two lines).
Using doubles, there are rounding errors. I could simply ignore them and use something like
d1 - d2 <= 0.0001
to compare the values, but I assume with further calculations the error could sum up until it becomes significant. So I thought I could round them after every possibly unprecise operation, but that turned out to produce much worse results, assumedly because the program also rounds unexact values (eg. 0.33333333... -> 0.3333300...).
Using BigDecimal would be far too slow.
What is the best way to solve this problem?
Inaccurate Method
When you are using numbers that require Precise calculations you need to be sure that you aren't doing something like: (and this is what it seems like you are currently doing)
This will result in the accumulation of rounding errors as the process continues; giving you extremely innacurate data long-term. In the above example, you are actually rounding off the starting float 4 times, each time it becomes more and more inaccurate!
Accurate Method
A better and more accurate way of obtaining numbers is to do this:
This will help you to avoid the accumulation of rounding errors because each calculation is based off of only 1 conversion and the results from that conversion are not compounded into the next calculation.
The best method of attack would be to start at the highest precision that is necessary, then convert on an as-needed basis, but leave the original intact. I would suggest you to follow the process from the second picture that I posted.
I started with integers as the vector coordinates because the game needs nothing more precise for the coordinates, but for all calculations I still would have to change to double vectors to get a clear result (eg. intersection between two lines).
It's important to note that you should not attempt to perform any type of rounding of your values if there is not noticeable impact on your end result; you will simply be doing more work for little to no gain, and may even suffer a performance decrease if done often enough.
This is a minor addition to the prior answer. When converting the float to an integer, it is important to round rather than just casting. In the following program, d is the largest double that is strictly less than 1.0. It could easily arise as the result of a calculation that would have result 1.0 in infinitely precise real number arithmetic.
The simple cast gets result 0. Rounding first gets result 1.
public class Test {
public static void main(String[] args) {
double d = Math.nextDown(1.0);
System.out.println(d);
System.out.println((int)d);
System.out.println((int)Math.round(d));
}
}
Output:
0.9999999999999999
0
1
Several months ago I had to implement a two-dimensional Fourier transformation in Java. While the results seemed sane for a few manual checks I wondered how a good test-driven approach would look like.
Basically what I did was that I looked at reasonable values of the DC components and compared the AC components if they roughly match the Mathematica output.
My question is: Which unit tests would you implement for a discrete Fourier transformation? How would you validate results returned by your calculation?
As for other unit-tests, you should consider small fixed input test-vectors for which results can easily be computed manually and compared against. For the more involved input test-vectors, a direct DFT implementation should be easy enough to implement and used to cross-validate results (possibly on top of your own manual computations).
As far as specific test vectors for one-dimensional FFT, you can start with the following from dsprelated, which they selected to exercise common flaws:
Single FFT tests - N inputs and N outputs
Input random data
Inputs are all zeros
Inputs are all ones (or some other nonzero value)
Inputs alternate between +1 and -1.
Input is e^(8*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j = sqrt(-1))
Input is cos(8*2*pi*i/N) for i = 0,1,2, ...,N-1.
Input is e^((43/7)*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j sqrt(-1))
Input is cos((43/7)*2*pi*i/N) for i = 0,1,2, ...,N-1.
Multi FFT tests - run continuous sets of random data
Data sets start at times 0, N, 2N, 3N, 4N, ....
Data sets start at times 0, N+1, 2N+2, 3N+3, 4N+4, ....
For two-dimensional FFT, you can then build on the above. The first three cases are still directly applicable (random data, all zeros, all ones). Others require a bit more work but are still manageable for small input sizes.
Finally google searches should yield some reference images (before and after transform) for a few common cases such as black & white squares, rectangle, circles which are can be used as reference (see for example http://www.fmwconcepts.com/misc_tests/FFT_tests/).
99.9% of the numerical and coding issues you will likely find will be found by testing with a random complex vectors and comparing with a direct DFT to a tolerance on the order of floating point precision.
Zero, constant, or sinusoidal vectors may help understand a failure by allowing your eye to catch issues like initialization, clipping, folding, scaling. But they will not typically find anything that the random case does not.
My kissfft library does a few extra tests related to fixed point issues -- not an issue if you are working in floating point.
Initially I have an array of time and an array of voltage and I have applied FFT and converted that time domain into frequency domain.After applying FFT I got an array of frequencies. Now I have cut off frequency and I need to implement Low pass filter on the same. I need to do this using JAVA. Could someone please refer me if there is any open source available or any idea of implementing the same. Any references that would be implemented using frequency values and cut off frequency would help.
I am completely new to this topic so my approach of question might be little weird. Thanks in advance for support!!!
Since you already have a array with the FFT values, you can implement a very crude low pass filter by just setting those FFT coefficients that correspond to frequencies over your cut-off value to zero.If you need a nicer filter you can implement a digital filter or find an LPF implementation online and just use that.
EDIT: After computing the FFT you don't get an array of frequencies, you get an array of complex numbers representing the magnitude and phase of the data.You should be able to know what frequency each and every complex number in the array corresponds to because the FFT result will correspond to evenly spaced frequencies ranging from 0 to f_s, where f_s is the sampling frequency you used to get your data.
A useful exercise might be to first try and plot a frequency spectrum, because after plotting it, it will be clear how you can discard high frequencies thus realising a LPF.This slightly similar post might help you: LINK
EDIT: 1) First you need to find the sampling frequency (f_s) of your data, this is the number of samples have taken every second.It can be computed using f_s = 1/T, where T is the time interval between any two consecutive samples in the time domain.
2) After this you divide f_c by f_s, where f_c is the cut-off frequency to get a constant k.
3) You then set all COMPLEX numbers above index ( k times N) in your array to zero, where N is the number of elements in your array, simple as that, that will give you a basic Low pass filter (LPF).
Rough, indicative (pseudo)code below:
Complex[] fftData = FFT(myData);
int N = fftData.Length;
float T = 0.001;
float f_c = 500; //f_c = 500Hz
float f_s = 1/T; //f_s = 1000Hz
float k = f_c/f_s;
int index = RoundToNextLargestInteger(k * N);
//Low pass filter
for(int i = index; index < N; index++)
fftData[i] = 0;
The fftData you receive in your case will not already be in the form of elements from the Complex class, so make sure you know how your data is represented and which data elements to set to zero.
This is not really a good way to do it though as a single frequency in your data can be spread over several bins because of leakage so the results would be nasty in that case.Ideally you would want to design a proper digital filter or just use some software library.So if you need a very accurate LPF, you can go through the normal process of designing analog LPF and then warping it to a digital filter as discussed in THIS document.
I would like to use FastFourierTransformation in order to identify patterns so as to predict future values of my monitoring metrics. What I'm trying to do is:
I monitor incoming traffic load, which is being repeated seasonally (high picks during daytime), with an additionally trend over a period of a week (lower traffic during weekends, also seasonally repeated).
Although I've tried some augmented regression algorithms, but I would also like to use the FFT in order to identify the most important coefficients, so as to recognize these two most important frequencies, and then try to extrapolate so as to predict the traffic in the near future.
I'm struggling with apache.commons.math3.transform.FastFourierTransformation, although my theoretical background in mathematics causes me some troubles.
Supposing that I use a doube [] array for storing my latest traffic load in the observed timeframe, I use the following code:
double [] initialSignal = getMonitoringData(timeslide);
FastFourierTransformer fft = new FastFourierTransformer(DftNormalization.STANDARD);
Complex [] result = fft.transform(initialSignal, TransformType.FORWARD);
However I'm not familiar with what the Complex [] array represents. Does the imaginary attribute of each Complex object in the array represents the relevant sinusoidal coefficient?
So, if I want to take the denoised initial signal I only have to set to zero the less significant coefficients of the Complex [] result array?
But still, if I have the following
Complex [] denoised = fft.transform(importantCoefficiants, TransformType.INVERSE);
The result will still be an array of Complex. How can i get the newly transformed x(t) values of the time series?
And how can I extrapolate in order to predict the x(t+1), x(t+2) ... x(t+n) values, after denoising the initial time series?
Well, I guess I found a solution yesterday night, pretty similar with erickson's answer.
I calculate the x^2+y^2 and then I take into account the most significant coefficients. I'm setting to zero the other elements of the array and then I perform a IFFT. My final question now is:
How I can extrapolate the given result in the Complex array so as to predict future values?
For instance, if I have n=4096 samples (Complex [4096] array) as my input, then I suppose that the value of x(n+1) will be the value of the array[0], the value of x(n+2) will be the value of array[1] etc?
I am implementing MFCC algorithm in Java.
There is a sample code here: http://www.ee.columbia.edu/~dpwe/muscontent/practical/mfcc.m at Matlab. However I have some problems with mel filter banking process. How to generate triangular windows and how to use them?
PS1: An article which has a part that describes MFCC: http://arxiv.org/pdf/1003.4083
PS2: If there is a document about MFCC algorithms steps basically, it will be good.
PS3: My main question is related to that: MFCC with Java Linear and Logarithmic Filters some implementations use both linear and logarithmic filter and some of them not. What is that filters and what is the center frequent concept. I follow that code:MFCC Java , what is the difference of it between that code: MFCC Matlab
Triangular windows as frequency band filters aren't hard to implement. You basically want to integrate the FFT data within each band (defined as the frequency space between center frequency i-1 and center frequency i+1).
You're basically looking for something like,
for(int bandIdx = 0; bandIdx < numBands; bandIdx++) {
int startFreqIdx = centerFreqs[bandIdx-1];
int centerFreqIdx = centerFreqs[bandIdx];
int stopFreqIdx = centerFreqs[bandIdx+1];
for(int freq = startFreqIdx; i < centerFreqIdx; i++) {
magnitudeScale = centerFreqIdx-startFreqIdx;
bandData[bandIdx] += fftData[freq]*(i-startFreqIdx)/magnitudeScale;
}
for(int freq = centerFreqIdx; i <= stopFreqIdx; i++) {
magnitudeScale = centerFreqIdx-stopFreqIdx;
bandData[bandIdx] += fftData[freq]*(i-stopFreqIdx)/magnitudeScale;
}
}
If you do not understand the concept of a "center frequency" or a "band" or a "filter," pick up an elementary signals textbook--you shouldn't be implementing this algorithm without understanding what it does.
As for what the exact center frequencies are, it's up to you. Experiment and pick (or find in publications) values that capture the information you want to isolate from the data. The reason that there are no definitive values, or even scale for values, is because this algorithm tries to approximate a human ear, which is a very complicated listening device. Whereas one scale may work better for, say, speech, another may work better for music, etc. It's up to you to choose what is appropriate.
Answer for the second PS: I found this tutorial that really helped me computing the MFCCs.
As for the triangular windows and the filterbanks, from what I understood, they do overlap, they do not extend to negative frequences and the whole process of computing them from the FFT spectrum and applying them back to it goes something like this:
Choose a minimum and a maximum frequency for the filters (for example, min freq = 300Hz - the minimum voice frequency and max frequency = your sample rate / 2. Maybe this is where you should choose the 1000Hz limit you were talking about)
Compute the mel values from the min and max chosen frequences. Formula here.
Compute N equally distanced values between these two mel values. (I've seen examples of different values for N, you can even find a efficiency comparison for different of values in this work, for my tests I've picked 26)
Convert these values back to Hz. (you can find the formula on the same wiki page) => array of N + 2 filter values
Compute a filterbank (filter triangle) for each three consecutive values, either how Thomas suggested above (being careful with the indexes) or like in the turorial recommended at the beginning of this post) => an array of arrays, size NxM, asuming your FFT returned 2*M values and you only use M.
Pass the whole power spectrum (M values obtained from FFT) through each triangular filter to get a "filterbank energy" for each filter (for each filterbank (N loop), multiply each magnitude obtained after FFT to each value in the corresponding filterbank (M loop) and add the M obtained values) => N-sized array of energies.
These are your filterbank energies that you can further apply a log to, apply the DCT and extract the MFCCs...