Выполните БПФ сигнала в Objective-C и сравните результаты с MATLAB

Я пытаюсь выполнить БПФ сигнала в Objective-C. Сигнал состоит из 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, и код, который я использовал для выполнения БПФ, следующий:

// -- 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 и INF, почему ??? Затем я помещаю это в MATLAB (чтобы проверить результат) и выполняю: plot (gainFFTTest)

и после того, как я увеличил масштаб, я вижу этот график:

введите описание изображения здесь

После этого я помещаю массив 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];

Затем я выполняю БПФ и строю график усиления:

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

И сюжет теперь правильный:

введите описание изображения здесь

  • # P11 #

Помогите, пожалуйста.


person Taglia    schedule 13.11.2014    source источник
comment
Похоже, вы использовали abs в MATLAB, но не в Objective-C. Это было намеренно?   -  person Ian MacDonald    schedule 13.11.2014
comment
Я выполняю пресс в Objective-C, выполняя sqrt (rePart ^ 2 + imPart ^ 2)   -  person Taglia    schedule 13.11.2014
comment
БПФ реальных данных симметрично. Может ли БПФ с объективной C вычислять только половину значений? Форма БПФ кажется такой же, если рассматривать только половину спектра. Коэффициент масштабирования может быть различным в зависимости от того, какой вид масштабирования используется алгоритм БПФ.   -  person Navan    schedule 13.11.2014


Ответы (2)


Ваш код Objective-C не соответствует коду Matlab:

  1. В коде Matlab нет окон. Кроме того, предоставленные вами тестовые данные, похоже, уже умножены на оконную функцию.

  2. Кажется, вы используете реализацию Radix2 в коде Objective-C. Matlab не использует Radix2, если длина сигнала не соответствует степени 2. См. http://mathworks.com/help/matlab/ref/fft.html, подробности в разделе "алгоритм".

Ваш код Objective-C кажется странным. Radix2 не определен для двух сигналов без мощности. Количество предоставленных образцов (180) не соответствует numSamples. Какие из этого последствия? Заполняет ли алгоритм оставшуюся часть сигнала нулями (заполнение нулями) или он просто считывает память после вашего массива?

person Diphtong    schedule 13.11.2014
comment
Вы правы, тестовые данные являются результатом полосовой фильтрации и затем умножены на окно Ханна. Результатом этого процесса является массив fftTest из 180 отсчетов. Если я сделаю заполнение нулями для остальных 76 образцов, результат не изменится. Моя цель - получить тот же результат, что и Matlab. Как я выполняю это в Objective-C? PS: Собираюсь отредактировать вопрос и удалить че часть окна - person Taglia; 13.11.2014

Я решил эту проблему, установив значение NAN и INF равным нулю и используя 256 сэмплов вместо 180.

person Taglia    schedule 20.11.2014