在 Objective-C 中执行信号的 FFT 并与 MATLAB 比较结果
Posted
技术标签:
【中文标题】在 Objective-C 中执行信号的 FFT 并与 MATLAB 比较结果【英文标题】:Perform a FFT of a signal in Objective-C and compare results with MATLAB 【发布时间】:2014-11-13 14:16:00 【问题描述】:我正在尝试在 Objective-C 中执行信号的 FFT。 该信号由 180 个样本组成。信号如下:
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;
在我的项目中,我导入了 Accelerate Framework,我用来执行 FFT 的代码如下:
// -- 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]);
那么我的输出幅度向量是:
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];
我经常获得 NAN i INF 值,为什么? 然后我把它放在 MATLAB 中(检查结果)并执行: 绘图(增益FFTTest)
并且,在我放大之后,我看到了这个情节:
在此之后,我使用以下命令将 testFFT 数组放入 MATLAB:
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];
然后我执行 FFT 并绘制增益:
gain = abs(fft(testFFT));
plot(gain)
现在的情节是正确的:
我哪里错了??如何在 Objective-C 中获得相同的结果?
请帮帮我。
【问题讨论】:
您似乎在 MATLAB 中使用了abs
,但在 Objective-C 中却没有。这是故意的吗?
我在 Objective-C 中通过 sqrt(rePart^2 + imPart^2) 执行 abs
真实数据的 FFT 是对称的。 Objective-C FFT 可以只计算一半的值吗?如果只考虑一半频谱,FFT 的形状似乎相同。比例因子可能会有所不同,具体取决于使用的 FFT 算法的缩放类型。
【参考方案1】:
您的 Objective-C 代码与 Matlab 代码不匹配:
matlab 代码中没有窗口。另外,你提供的测试数据好像已经乘了一个窗函数。
您似乎在 Objective-C 代码中使用了 Radix2 实现。如果信号的长度与 2 的幂不匹配,则 Matlab 不使用 Radix2。有关详细信息,请参阅http://mathworks.com/help/matlab/ref/fft.html,“算法”部分。
您的 Objective-C 代码看起来很奇怪。 Radix2 未定义为非 2 信号的幂。提供的样本数 (180) 与 numSamples 不匹配。这意味着什么?该算法是用零(零填充)填充信号的其余部分,还是只读取数组后面的内存?
【讨论】:
你是对的,测试数据是带通滤波的结果,然后乘以一个汉恩窗。此过程的结果是 180 个样本的数组“fftTest”。如果我对其余 76 个样本进行零填充,则结果不会改变。我的目标是获得与 Matlab 相同的结果。我如何在 Objective-C 中执行此操作? PS:我要编辑问题并删除“窗口”的部分【参考方案2】:我通过将 NAN 和 INF 值设置为零并使用 256 个样本而不是 180 个样本来解决此问题。
【讨论】:
以上是关于在 Objective-C 中执行信号的 FFT 并与 MATLAB 比较结果的主要内容,如果未能解决你的问题,请参考以下文章