Perform a FFT of a signal in Objective-C and compare results with MATLAB

1.4k views Asked by At

I'm trying to perform the FFT of a signal in Objective-C. The signal is composed of 180 samples. The signal is the following:

float testFFT [180] = { 0.0000000000, 0.0000432091, 0.0001739833, 0.0003786624, 0.0006653523, 0.0010579729, 0.0015538626, 0.0022084275, 0.0029233105, 0.0037457265, 0.0048239902, 0.0061722184, 0.0074678478, 0.0019116795, -0.0216427371, -0.0583566576, -0.0879606530, -0.0966484919, -0.0844414756, -0.0587274097, -0.0275895316, 0.0020122994, 0.0238022581, 0.0301328432, 0.0223602522, 0.0108049158, 0.0026056657, 0.0015842463, 0.0078394171, 0.0178532675, 0.0289764665, 0.0387034491, 0.0457277447, 0.0503653251, 0.0511394553, 0.0495931208, 0.0491546877, 0.0486858748, 0.0486131087, 0.0533984452, 0.0587649047, 0.0659925416, 0.0777209774, 0.0856716558, 0.0555341654, -0.1010383219, -0.3626580238, -0.5730977058, -0.6356759071, -0.5587731600, -0.4057232738, -0.2299835384, -0.0666809455, 0.0577908531, 0.1170516908, 0.1059532985, 0.0634752810, 0.0284998771, 0.0149525786, 0.0262031760, 0.0470281616, 0.0667090788, 0.0911477804, 0.1096955463, 0.1211226359, 0.1271539181, 0.1249239892, 0.1236920506, 0.1237676740, 0.1250490546, 0.1243178397, 0.1247144639, 0.1260439157, 0.1231973395, 0.1264088154, 0.1277698576, -0.0030977963, -0.3769126236, -0.8328822851, -1.1014552116, -1.0855975151, -0.8706340790, -0.5911422372, -0.3257140219, -0.0960753635, 0.0647964701, 0.1323186159, 0.1257916987, 0.0897259787, 0.0630174652, 0.0530946776, 0.0599082038, 0.0814570710, 0.1065363511, 0.1312004477, 0.1502322406, 0.1570600569, 0.1507443786, 0.1410262287, 0.1309887618, 0.1199141294, 0.1154099405, 0.1160193905, 0.1228033155, 0.1373534203, 0.1516684294, 0.1679655612, 0.1372354180, -0.1066413969, -0.5384752750, -0.8941160440, -0.9979212284, -0.8646196723, -0.6145014763, -0.3477802575, -0.1164548695, 0.0449491963, 0.1089080572, 0.0893236622, 0.0330192894, -0.0108435927, -0.0175555795, 0.0047061597, 0.0339520164, 0.0558914244, 0.0686639696, 0.0742127448, 0.0779310316, 0.0802902952, 0.0771160051, 0.0714451671, 0.0660981461, 0.0637993589, 0.0645155609, 0.0667568296, 0.0722958520, 0.0757482499, 0.0236506276, -0.1267153770, -0.3023732007, -0.3952195346, -0.3767756522, -0.2849329114, -0.1723687500, -0.0716818050, 0.0028261179, 0.0375415571, 0.0343864709, 0.0144051891, -0.0021018211, -0.0056255818, 0.0027398649, 0.0138968918, 0.0204720702, 0.0226374995, 0.0215674732, 0.0184285343, 0.0154026123, 0.0144131510, 0.0145750465, 0.0143866902, 0.0138069429, 0.0127558541, 0.0114914598, 0.0105097489, 0.0059011118, -0.0082570817, -0.0260418169, -0.0354200974, -0.0332562923, -0.0243141986, -0.0146232471, -0.0073889960, -0.0028967261, -0.0005872814, 0.0001664309, 0.0001607906, 0.0000362319, 0.0000018391, 0.0000000001};

In my project I've imported the Accelerate Framework and the code I used to perform the FFT is the following :

// -- Number of Sample
int numSamples = 256; // i use 256 because if i use 128 i don't considered 52 values

// -- Init FFT
// - Setup the length
vDSP_Length log2n = log2f(numSamples);

FFTSetup fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);

int nOver2 = numSamples/2;

// - Define complex buffer
COMPLEX_SPLIT A;
A.realp = (float *) malloc(nOver2*sizeof(float));
A.imagp = (float *) malloc(nOver2*sizeof(float));

// - Pack samples:
vDSP_ctoz((COMPLEX*)testFFT, 2, &A, 1, numSamples/2);


// -- Run FFT
vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);

// -- Convert COMPLEX_SPLIT A result to magnitudes
float amp[256];
amp[0] = A.realp[0]/(numSamples*2);

for(int i=1; i<numSamples; i++) {
    amp[i]=sqrt(A.realp[i]*A.realp[i]+A.imagp[i]*A.imagp[i]);
}

Then my output magnitude vector is :

gainFFTTest = [ -0.022274, 8.984702, 4.144551, 0.809363, 0.941445, 2.347171, 7.364040, 16.668034, 23.730299, 21.198763, 11.301848, 3.042607, 1.467086, 2.339780, 4.816690, 10.835640, 17.146097, 17.648199, 11.441965, 4.918188, 2.744555, 2.347548, 3.812189, 7.538163, 12.398130, 14.082799, 10.534361, 5.591731, 3.525628, 2.503175, 2.460673, 3.326554, 5.311335, 6.440503, 5.227306, 2.916733, 1.815048, 1.607442, 1.587724, 1.587670, 2.045040, 2.519320, 2.300229, 1.566618, 0.928839, 0.690373, 0.905959, 1.130702, 1.337159, 1.626698, 1.553285, 1.114764, 0.753150, 0.591139, 0.653807, 0.852154, 0.836321, 0.835025, 0.851975, 0.664267, 0.443333, 0.324886, 0.312793, 0.420463, 0.429140, 0.355254, 0.340838, 0.290471, 0.214697, 0.174454, 0.153486, 0.190136, 0.208401, 0.164705, 0.138394, 0.115397, 0.075669, 0.065181, 0.077329, 0.110584, 0.143098, 0.131150, 0.086918, 0.063639, 0.051252, 0.064340, 0.077155, 0.072525, 0.080241, 0.088438, 0.070221, 0.051208, 0.040207, 0.028501, 0.025500, 0.029908, 0.042129, 0.045339, 0.033957, 0.019551, 0.015710, 0.025570, 0.028711, 0.017500, 0.006169, 0.013390, 0.013368, 0.007762, 0.005007, 0.008410, 0.010856, 0.009631, 0.012508, 0.018056, 0.019384, 0.014050, 0.006475, 0.005373, 0.006383, 0.006624, 0.006779, 0.006790, 0.005996, 0.004189, 0.002242, 0.001977, 0.002130, 0.001396, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000];

Often i obtained NAN i INF values why ??? Then I put this in MATLAB (to check the result ) and perform : plot(gainFFTTest)

and, after I zoomed in as much, I see this plot :

enter image description here

After this i Put the testFFT array in MATLAB with this command:

testFFT = [ 0.0000000000, 0.0000432091, 0.0001739833, 0.0003786624, 0.0006653523, 0.0010579729, 0.0015538626, 0.0022084275, 0.0029233105, 0.0037457265, 0.0048239902, 0.0061722184, 0.0074678478, 0.0019116795, -0.0216427371, -0.0583566576, -0.0879606530, -0.0966484919, -0.0844414756, -0.0587274097, -0.0275895316, 0.0020122994, 0.0238022581, 0.0301328432, 0.0223602522, 0.0108049158, 0.0026056657, 0.0015842463, 0.0078394171, 0.0178532675, 0.0289764665, 0.0387034491, 0.0457277447, 0.0503653251, 0.0511394553, 0.0495931208, 0.0491546877, 0.0486858748, 0.0486131087, 0.0533984452, 0.0587649047, 0.0659925416, 0.0777209774, 0.0856716558, 0.0555341654, -0.1010383219, -0.3626580238, -0.5730977058, -0.6356759071, -0.5587731600, -0.4057232738, -0.2299835384, -0.0666809455, 0.0577908531, 0.1170516908, 0.1059532985, 0.0634752810, 0.0284998771, 0.0149525786, 0.0262031760, 0.0470281616, 0.0667090788, 0.0911477804, 0.1096955463, 0.1211226359, 0.1271539181, 0.1249239892, 0.1236920506, 0.1237676740, 0.1250490546, 0.1243178397, 0.1247144639, 0.1260439157, 0.1231973395, 0.1264088154, 0.1277698576, -0.0030977963, -0.3769126236, -0.8328822851, -1.1014552116, -1.0855975151, -0.8706340790, -0.5911422372, -0.3257140219, -0.0960753635, 0.0647964701, 0.1323186159, 0.1257916987, 0.0897259787, 0.0630174652, 0.0530946776, 0.0599082038, 0.0814570710, 0.1065363511, 0.1312004477, 0.1502322406, 0.1570600569, 0.1507443786, 0.1410262287, 0.1309887618, 0.1199141294, 0.1154099405, 0.1160193905, 0.1228033155, 0.1373534203, 0.1516684294, 0.1679655612, 0.1372354180, -0.1066413969, -0.5384752750, -0.8941160440, -0.9979212284, -0.8646196723, -0.6145014763, -0.3477802575, -0.1164548695, 0.0449491963, 0.1089080572, 0.0893236622, 0.0330192894, -0.0108435927, -0.0175555795, 0.0047061597, 0.0339520164, 0.0558914244, 0.0686639696, 0.0742127448, 0.0779310316, 0.0802902952, 0.0771160051, 0.0714451671, 0.0660981461, 0.0637993589, 0.0645155609, 0.0667568296, 0.0722958520, 0.0757482499, 0.0236506276, -0.1267153770, -0.3023732007, -0.3952195346, -0.3767756522, -0.2849329114, -0.1723687500, -0.0716818050, 0.0028261179, 0.0375415571, 0.0343864709, 0.0144051891, -0.0021018211, -0.0056255818, 0.0027398649, 0.0138968918, 0.0204720702, 0.0226374995, 0.0215674732, 0.0184285343, 0.0154026123, 0.0144131510, 0.0145750465, 0.0143866902, 0.0138069429, 0.0127558541, 0.0114914598, 0.0105097489, 0.0059011118, -0.0082570817, -0.0260418169, -0.0354200974, -0.0332562923, -0.0243141986, -0.0146232471, -0.0073889960, -0.0028967261, -0.0005872814, 0.0001664309, 0.0001607906, 0.0000362319, 0.0000018391, 0.0000000001];

Then i perform the FFT and plot the gain :

gain = abs(fft(testFFT));
plot(gain)

And the plot now is correct :

enter image description here

  • Where am I wrong ?? how can I get the same results in Objective-C?

Please help me.

2

There are 2 answers

0
Taglia On BEST ANSWER

I Resolved this issue by putting the NAN and INF value at zero and by using 256 samples instead 180.

1
Diphtong On

Your Objective-C code does not match the Matlab code:

  1. There is no windowing in the matlab code. In addition, the test data you provided seems to be already multiplied by a window function.

  2. You seem to use an Radix2 implementation in the Objective-C code. Matlab does not use Radix2 if the length of the signal does not match a power of 2. Refer to http://mathworks.com/help/matlab/ref/fft.html , section "algorithm" for details.

Your Objective-C code seems strange. Radix2 is not defined for non power of 2 signals. The number of samples supplied (180) does not match numSamples. What are the implications of this? Does the algorithm fill the remaining part of the signal with zeros (zero-padding), or will it just read the memory following your array?