Accelerate vDSP 프레임 워크를 사용하여 기존 FFT 기반 저역 통과 필터를 iOS로 이식하려고합니다.iOS 저속 통과 FFT 필터 미러링 결과 가속
FFT가 샘플의 1/4에 대해 예상대로 작동하는 것처럼 보입니다. 그러나 그 후에 결과는 틀린 것처럼 보이고, 훨씬 더 이상한 것은 미러됩니다 (상반기의 대부분을 미러링하는 신호의 마지막 절반으로).
아래 테스트 응용 프로그램의 결과를 볼 수 있습니다. 먼저 샘플링 된 원래 데이터를 플로팅하고 예상되는 필터링 된 결과의 예제 (15Hz보다 높은 신호 필터링), 마지막으로 현재 FFT 코드의 결과 (원하는 결과와 예제 FFT 결과는 원래의 데이터)
아래와내 로우 패스 필터의 실제 코드가 같이 라이브러리의 비 2 제곱 크기 처리 된 원래 코드에서
double *lowpassFilterVector(double *accell, uint32_t sampleCount, double lowPassFreq, double sampleRate)
{
double stride = 1;
int ln = log2f(sampleCount);
int n = 1 << ln;
// So that we get an FFT of the whole data set, we pad out the array to the next highest power of 2.
int fullPadN = n * 2;
double *padAccell = malloc(sizeof(double) * fullPadN);
memset(padAccell, 0, sizeof(double) * fullPadN);
memcpy(padAccell, accell, sizeof(double) * sampleCount);
ln = log2f(fullPadN);
n = 1 << ln;
int nOver2 = n/2;
DSPDoubleSplitComplex A;
A.realp = (double *)malloc(sizeof(double) * nOver2);
A.imagp = (double *)malloc(sizeof(double) * nOver2);
// This can be reused, just including it here for simplicity.
FFTSetupD setupReal = vDSP_create_fftsetupD(ln, FFT_RADIX2);
vDSP_ctozD((DSPDoubleComplex*)padAccell,2,&A,1,nOver2);
// Use the FFT to get frequency counts
vDSP_fft_zripD(setupReal, &A, stride, ln, FFT_FORWARD);
const double factor = 0.5f;
vDSP_vsmulD(A.realp, 1, &factor, A.realp, 1, nOver2);
vDSP_vsmulD(A.imagp, 1, &factor, A.imagp, 1, nOver2);
A.realp[nOver2] = A.imagp[0];
A.imagp[0] = 0.0f;
A.imagp[nOver2] = 0.0f;
// Set frequencies above target to 0.
// This tells us which bin the frequencies over the minimum desired correspond to
NSInteger binLocation = (lowPassFreq * n)/sampleRate;
// We add 2 because bin 0 holds special FFT meta data, so bins really start at "1" - and we want to filter out anything OVER the target frequency
for (NSInteger i = binLocation+2; i < nOver2; i++)
{
A.realp[i] = 0;
}
// Clear out all imaginary parts
bzero(A.imagp, (nOver2) * sizeof(double));
//A.imagp[0] = A.realp[nOver2];
// Now shift back all of the values
vDSP_fft_zripD(setupReal, &A, stride, ln, FFT_INVERSE);
double *filteredAccell = (double *)malloc(sizeof(double) * fullPadN);
// Converts complex vector back into 2D array
vDSP_ztocD(&A, stride, (DSPDoubleComplex*)filteredAccell, 2, nOver2);
// Have to scale results to account for Apple's FFT library algorithm, see:
// http://developer.apple.com/library/ios/#documentation/Performance/Conceptual/vDSP_Programming_Guide/UsingFourierTransforms/UsingFourierTransforms.html#//apple_ref/doc/uid/TP40005147-CH202-15952
double scale = (float)1.0f/fullPadN;//(2.0f * (float)n);
vDSP_vsmulD(filteredAccell, 1, &scale, filteredAccell, 1, fullPadN);
// Tracks results of conversion
printf("\nInput & output:\n");
for (int k = 0; k < sampleCount; k++)
{
printf("%3d\t%6.2f\t%6.2f\t%6.2f\n", k, accell[k], padAccell[k], filteredAccell[k]);
}
// Acceleration data will be replaced in-place.
return filteredAccell;
}
입력 데이터; 내 Accelerate 코드에서 가장 가까운 2의 제곱으로 입력을 채 웁니다. 아래 샘플 테스트의 경우 원본 샘플 데이터는 1000 샘플이므로 1024로 채워집니다. 결과에 영향을 미치지는 않을지 모르지만 가능한 차이점을 위해 포함합니다. 당신이 솔루션을 실험 할 경우
, 당신은합니다 (FFTTest 폴더에) 여기에 그래프를 생성하는 샘플 프로젝트 다운로드 할 수있는 통찰력을위한
이감사합니다, 나는 일을하지했습니다 전에 FFT를 사용했기 때문에 뭔가 중요한 것을 놓친 것처럼 느껴졌습니다.
하나의 큰 문제의 정당한 권력은보다 더 FFT 길이를 지원하고있는 주파수에 벽돌 벽 필터를 적용하려고 이와 같은 도메인은 시간 영역에서 거대한 인공물을 생성합니다. 이를 피하기 위해 윈도우 화 방법을 사용해야합니다. –
해결책을 찾았습니까? – NTNT