我实现了上述算法(https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm)。 这是完整的工作代码。 我在非交错立体声回调中从麦克风接收流输入。 然后我用输入样本填充缓冲区,并将该缓冲区处理为fft和ifft 功能。 最后,我使用指针将处理后的缓冲区发送到输出。 我使用Asio4all V2。 我真的不明白问题出在哪里,因为它确实可以正常工作,但是我无法超越N = 16或输出听起来断断续续。
非常感谢。
回调+主:
#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"
#include "FFT.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#define NUM_SECONDS (10)
typedef struct
{
}
paTestData;
static int patestCallback( void *INbuffers[2], void *OUTbuffers[2],
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *inL = (float *) INbuffers [0];
float *inR = (float *) INbuffers [1];
float *outL = (float *) OUTbuffers[0];
float *outR = (float *) OUTbuffers[1];
unsigned long i;
(void) timeInfo;
(void) statusFlags;
for( i=0; i<framesPerBuffer; i++ )
{
for(int i=0; i<N; i++)
{
Y[i] = *inL + 0*I;
}
*inL++;
fft(Y, N);
ifft(Y, N);
for(int i=0; i<N; i++)
{
p_out=&Y[i];
}
*outL++ = *p_out++;
*outR++ = *p_out++;
}
return paContinue;
}
int main()
{
PaStreamParameters inputParameters;
PaStreamParameters outputParameters;
PaStream *stream;
paTestData data;
Pa_Initialize();
inputParameters.device = Pa_GetDefaultInputDevice();
inputParameters.channelCount = 2;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0;
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = Pa_GetDefaultOutputDevice();
outputParameters.channelCount = 2;
outputParameters.sampleFormat = paFloat32 | paNonInterleaved;
outputParameters.suggestedLatency = 0;
outputParameters.hostApiSpecificStreamInfo = NULL;
Pa_OpenStream( &stream,
&inputParameters,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff,
patestCallback,
&data );
Pa_StartStream( stream );
Pa_Sleep( NUM_SECONDS * 1000);
Pa_StopStream( stream );
Pa_CloseStream( stream );
}
标题:
#ifndef FFT_H_INCLUDED
#define FFT_H_INCLUDED
#include <stdio.h>
#include <math.h>
#include <complex.h>
#define N (16)
complex Y[N];
complex *p_out;
void separate (complex *a, int n)
{
complex b[N/2];
for(int i=0; i<n/2; i++) // copy all odd elements to b
b[i] = a[i*2+1];
for(int i=0; i<n/2; i++) // copy all even elements to lower-half of a[]
a[i] = a[i*2];
for(int i=0; i<n/2; i++) // copy all odd (from heap) to upper-half of a[]
a[i+n/2] = b[i];
}
complex fft(complex *X, int m) // forward fft
{
if(m < 2) {
// bottom of recursion.
// Do nothing here, because already X[0] = x[0]
} else {
separate(X, m); // all evens to lower half, all odds to upper half
fft(X, m/2); // recurse even items
fft(X+m/2, m/2); // recurse odd items
for(int k=0; k<m/2; k++) // combine results of two half recursions
{
complex e = X[k ]; // even
complex o = X[k+m/2]; // odd
complex w = cexp( 0 + (-2.*M_PI*k/m)*I ); // w is the twiddle-factor
X[k ] = e + w * o;
X[k+m/2] = e - w * o;
}
}
}
float ifft(complex *X, int m) // inverse fft
{
for (int i=0; i<m; i++)
{
X[i]=conj(X[i]); // conjugate the complex array
}
fft(X, m); // forward fft
for (int i=0; i<m; i++)
{
X[i]=conj(X[i]); // conjugate the complex array again
}
for (int i=0; i<m; i++)
{
X[i] /= m; // scale the numbers
}
}
#endif // FFT_H_INCLUDED