1

我正在通过包含 320 个样本的数据包中的套接字连接接收 PCM 数据。声音的采样率为每秒 8000 个样本。我正在做这样的事情:

int size = 160 * 2;//160;
int isinverse = 1;
kiss_fft_scalar zero;
memset(&zero,0,sizeof(zero));
kiss_fft_cpx fft_in[size];
kiss_fft_cpx fft_out[size];
kiss_fft_cpx fft_reconstructed[size];

kiss_fftr_cfg fft = kiss_fftr_alloc(size*2 ,0 ,0,0);
kiss_fftr_cfg ifft = kiss_fftr_alloc(size*2,isinverse,0,0);

for (int i = 0; i < size; i++) {
    fft_in[i].r = zero;
    fft_in[i].i = zero;
    fft_out[i].r = zero;
    fft_out[i].i = zero;
    fft_reconstructed[i].r = zero;
    fft_reconstructed[i].i = zero;
}

// got my data through socket connection

for (int i = 0; i < size; i++) {
     // samples are type of short
     fft_in[i].r = samples[i];
     fft_in[i].i = zero;
     fft_out[i].r = zero;
     fft_out[i].i = zero;
 }

 kiss_fftr(fft, (kiss_fft_scalar*) fft_in, fft_out);
 kiss_fftri(ifft, fft_out, (kiss_fft_scalar*)fft_reconstructed);

 // lets normalize samples
 for (int i = 0; i < size; i++) {
     short* samples = (short*) bufTmp1;
     samples[i] = rint(fft_reconstructed[i].r/(size*2));
 }

之后我填充 OpenAL 缓冲区并播放它们。一切正常,但我想对 和 之间的音频进行一些kiss_fftr过滤kiss_fftri。我认为的起点是将声音从时域转换为频域,但我真的不明白我从kiss_fftr函数接收到什么样的数据。每个复数中存储了哪些信息,它的实部和虚部可以告诉我有关频率的信息。而且我不知道哪些频率被覆盖(什么频率跨度)fft_out- 哪些索引对应于哪些频率。

我是信号处理和傅里叶变换主题的新手。

有什么帮助吗?

4

3 回答 3

2

I will try to answer your questions directly.

// a) the real and imaginary components of the output need to be combined to calculate the amplitude at each frequency. 

float ar,ai,scaling; 

scaling=1.0/(float)size;

// then for each output [i] from the FFT...

ar = fft_out[i].r; 
ai = fft_out[i].i; 
amplitude[i] = 2.0 * sqrtf( ar*ar + ai*ai ) * scaling ;

// b) which index refers to which frequency? This can be calculated as follows. Only the first half of the FFT results are needed (assuming your 8KHz sampling rate) 

for(i=1;i<(size/2);i++) freq = (float)i / (1/8000) / (float)size ; 

// c)  phase (range +/- PI) for each frequency is calculated like this: 

phase[i] = phase = atan2(fft_out[i].i / fft_out[i].r);
于 2013-09-27T09:25:04.447 回答
2

在双脚进入 C 实现之前,请熟悉数字滤波器,尤其是FIR 滤波器

您可以使用诸如GNU Octave 的信号工具箱之类的东西来设计 FIR 滤波器。查看命令 fir1(最简单的)、firls 或 remez。或者,您可以通过网页设计 FIR 滤波器。在网上快速搜索“online fir filter design”发现了这个(我没用过,但它似乎使用了 remez 或 firpm 命令中使用的等波纹设计)

尝试首先使用直接卷积(没有 FFT)来实现您的过滤器,看看速度是否可以接受——这是一条更简单的路径。如果您需要基于 FFT 的方法,kissfft/tools/kiss_fastfir.c 文件中有一个重叠保存的示例实现。

于 2012-06-06T12:47:03.660 回答
1

您可能想要研究的是使用重叠添加或重叠保存算法的 FFT 快速卷积。您需要将每个 FFT 的长度扩展为所需滤波器的脉冲长度。这是因为 (1) FFT/IFFT 卷积是圆形的,并且 (2) FFT 阵列结果中的每个索引对应于几乎所有频率(Sinc 形响应),而不仅仅是一个(即使大部分接近一个),所以任何一个bin 修改将在整个频率响应中泄漏(某些精确的周期性频率除外)。

于 2012-06-05T15:23:02.867 回答