我正在借助FFT对两个整数信号进行卷积,但是不知何故我做不到。我不确定FFT的实现是否正确。尤其是数学部分。
大修改: 我现在发布了所有代码。抱歉,我不从此开始。我确定错误只是在FFT部分,但可能还有更多我忽略的问题。我知道代码很乱而且不干净。一切都是零散的,可以用更简单,更简洁的方式进行编程,但是我正在一点一点地进行测试。至于输入,它从命令行读取两个信号。建立为一个数字,表示信号有多大,信号以整数数组eq 2表示:[1,-1]和10:[0,0,0,1,1,1,1,0,0, 0]。然后,应通过对两个信号执行FFT,对信号进行卷积,然后进行逐位乘法。对结果信号进行逆FFT。再次打印其长度,然后打印包含整数的数组。打印本身正确,但是结果数组中的值不正确。我希望现在再次变得更加清楚,对不起,谢谢您的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
double PI;
int *readSignal(int *len) { //reads the signal
int *x;
char c;
scanf("%d:", len);
x = calloc(*len, sizeof(int));
do c = getchar(); while (c != '[');
if (len > 0) {
scanf("%d", &x[0]);
for (int i=1; i < *len; i++) scanf(",%d", &x[i]);
}
do c = getchar(); while (c != ']');
return x;
}
void printSignal(int len, int *x) { //prints the signal
printf("%d: [", len);
if (len > 0) {
printf("%d", x[0]);
for (int i=1; i < len; i++)
printf(",%d", x[i]);
}
printf("]\n");
}
void *padSignal(int len, int lenSig, int *x) { //ensures that the signal is of size 2^n by padding it with 0's
int *padded;
padded = calloc(len, sizeof(int));
for (int i=0; i < lenSig; i++) {
padded[i] = x[i];
}
return padded;
}
void fft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
fft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
void ifft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
ifft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*-2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*-2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
int checkPowerofTwo(double len) { //checks for the closed power of 2
double x = 1;
while(len > pow(2,x)) {
x++;
}
return pow(2,x);
}
int main(int argc, char *argv[]) {
int lenH, *H;
int lenX, *X;
int *paddedX;
int *paddedH;
double length;
H=readSignal(&lenH); //reads in the signal H
X=readSignal(&lenX); //reads in signal X
length = lenH+lenX-1;
paddedH=padSignal((length),lenH,H); //pads the signal to the length
paddedX=padSignal((length),lenX,X); // pads the signal to the length
double complex *signalX = calloc(length, sizeof(double complex)); //creats a complex signal X and fills it with paddedX
for (int i = 0; i<length; i++) {
signalX[i] = paddedX[i];
}
double complex *signalH = calloc(length, sizeof(double complex)); // same for H
for (int i = 0; i<length; i++) {
signalH[i] = paddedH[i];
}
fft(signalX, length, 1); //performs the fast fourier transform on X
fft(signalH,length, 1); // performs the fast fourier transfom on H
double complex *signalY = calloc(length, sizeof(double complex)); //makes complex signal Y
for (int i = 0; i<length; i++) { //performs the convolution
signalY[i] = signalX[i]*signalH[i];
}
ifft(signalY, length,1);
int *output = calloc(length, sizeof(int)); //creates the final output signal
for (int i = 0; i<length; i++) {
output[i] = creal(signalY[i]);
}
printSignal(length,output);
free(signalX);
free(signalH);
free(signalY);
free(H);
free(X);
free(paddedH);
free(paddedX);
free(output);
return 0;
}
答案 0 :(得分:2)
在:
if(i % 2 ==0 && i != 0)
您为什么要排除i == 0
?在if(i % 2 ==0)
和fft
中将其都更改为ifft
。
在fft
和ifft
中,以下行:
for(int i = 0; i<lenght/2-1; i++) {
应为:
for(int i = 0; i<lenght/2; i++) {
在ifft
中,递归意外地使用了fft
:
fft(signalEVEN,lenght/2, power+1);
fft(signalODD,lenght/2, power+1);
将其更改为ifft
。
calloc
调用不需要那么多空间:
calloc((lenght/2 + 1), sizeof(double complex));
可以是:
calloc((lenght/2), sizeof(double complex));
此外,的正确拼写是“ length”。
在修复了这些问题后,fft
和ifft
例程似乎可用于某些肤浅的情况。