Kiss FFT bin 幅度
我花了很多时间研究 FFT。我对使用 KISSFFT 特别感兴趣,因为它是一个非常可移植的 C 实现。
我仍然很不清楚如何将 i[x] 和 r[x] 转换为频率仓的幅度。因此创建了一个signed int 16版本的sin。我有 512 个正弦波样本。我期望看到一个带有数据的 Bin,其余的为零。不是这样...
这是我的代码...
- (IBAction)testFFT:(id)sender{
NSLog(@"testFFT");
static double xAxis = 0;
static int sampleCount = 0;
static double pieSteps;
static double fullSinWave = 3.14159265*2;
static double sampleRate = 44100;
static double wantedHz = 0;
int octiveOffset;
char * globalString = stringToSend;
SInt16 dataStream[512];
// Notes: ioData contains buffers (may be more than one!)
// Fill them up as much as you can. Remember to set the size value in each buffer to match how
// much data is in the buffer.
for (int j = 0; j < 512; j++) {
wantedHz = 1000;
pieSteps = fullSinWave/(sampleRate/wantedHz);
xAxis += pieSteps;
dataStream[j] = (SInt16)(sin(xAxis) * 32768.0);
NSLog(@"%d) %d", j, dataStream[j]);
}
kiss_fft_cfg mycfg = kiss_fft_alloc(512,0,NULL,NULL);
kiss_fft_cpx* in_buf = malloc(sizeof(kiss_fft_cpx)*512);
kiss_fft_cpx* out_buf = malloc(sizeof(kiss_fft_cpx)*512);
for (int i = 0;i < 512;i++){
in_buf[i].r = dataStream[i];
in_buf[i].i = dataStream[i];
}
kiss_fft(mycfg,in_buf, out_buf);
for (int i = 0;i < 256;i++){
ix = out_buf[i].i;
rx = out_buf[i].r;
printfbar(sqrt(ix*ix+rx*rx)););
}
}
我得到的结果看起来像这样...
***** ********************* **************************** ********************* ************************ ********************* **************************** ********************* ***** ********************* **************************** ********************* ***************** ********************* **************************** ********************* ***** ********************* **************************** ********************* ************************ ********************* **************************** *********************
I have been spending quite a bit of time studying FFT's. I am in particular interesting in using KISSFFT because it is a very portable C implementation.
I am still very unclear how to turn i[x] and r[x] into a frequency bin's amplitude. So created a signed int 16 version of sin. I have 512 samples of my sin wave. I expected to see one Bin with data and the rest at zero. Not so...
Here is my code...
- (IBAction)testFFT:(id)sender{
NSLog(@"testFFT");
static double xAxis = 0;
static int sampleCount = 0;
static double pieSteps;
static double fullSinWave = 3.14159265*2;
static double sampleRate = 44100;
static double wantedHz = 0;
int octiveOffset;
char * globalString = stringToSend;
SInt16 dataStream[512];
// Notes: ioData contains buffers (may be more than one!)
// Fill them up as much as you can. Remember to set the size value in each buffer to match how
// much data is in the buffer.
for (int j = 0; j < 512; j++) {
wantedHz = 1000;
pieSteps = fullSinWave/(sampleRate/wantedHz);
xAxis += pieSteps;
dataStream[j] = (SInt16)(sin(xAxis) * 32768.0);
NSLog(@"%d) %d", j, dataStream[j]);
}
kiss_fft_cfg mycfg = kiss_fft_alloc(512,0,NULL,NULL);
kiss_fft_cpx* in_buf = malloc(sizeof(kiss_fft_cpx)*512);
kiss_fft_cpx* out_buf = malloc(sizeof(kiss_fft_cpx)*512);
for (int i = 0;i < 512;i++){
in_buf[i].r = dataStream[i];
in_buf[i].i = dataStream[i];
}
kiss_fft(mycfg,in_buf, out_buf);
for (int i = 0;i < 256;i++){
ix = out_buf[i].i;
rx = out_buf[i].r;
printfbar(sqrt(ix*ix+rx*rx)););
}
}
I am getting results that look like this....
***** ********************* **************************** ********************* ************************ ********************* **************************** ********************* ***** ********************* **************************** ********************* ***************** ********************* **************************** ********************* ***** ********************* **************************** ********************* ************************ ********************* **************************** *********************
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,一些编程更改
将有助于减少数字错误。
会将输入缓冲区设置为
sin(x)
,之前您已将其设置为sin(x) + j*sin(x)
,其中j = sqrt (-1)
。将
wantedHz = 1000;
移出循环看起来更好。还有一个更根本的问题:您设置
wantedHz = 1000
。采样率为 44.1 kHz 时,这相当于44100 点/秒 * (1/1000) 秒/周期 = 44.1 点/周期
。使用 512 点的缓冲区,您将在缓冲区中获得 11.6 个正弦波周期。非整数周期会导致泄漏。不过,在开始讨论之前,请尝试设置
wantedHz = 12*44100.0/512
以在缓冲区中提供正好 12 个周期。您应该在转换中看到两个尖峰:一个位于索引 12 处,另一个位于索引 511-12 处。您会看到两个尖峰的原因是
sin(w_0*x)
的变换为j*{-delta(w-w_0) - delta(w+w_0)}
代码>.也就是说,您在变换的虚部中的 w_0 和 -w_0 处获得脉冲函数。它们处于当前位置的原因是变换从 0 到 2*pi。执行此操作后,返回到
wantedH = 1000
,为您提供缓冲区中的非整数周期数。您应该看到一个宽阔的帐篷形结果,以垃圾箱 11 和 511-11 为中心。您应该将dataStream
乘以窗口函数(Hann 很好)减少这种效应的影响。A couple of programming changes, first of all:
will help reduce numeric error.
will set the input buffer to
sin(x)
, previously you had it set tosin(x) + j*sin(x)
, wherej = sqrt(-1)
.Moving
wantedHz = 1000;
out of the loop looks better.And a more fundamental issue: you set
wantedHz = 1000
. With a sample rate of 44.1 kHz this corresponds to44100 points/sec * (1/1000) sec/cycle = 44.1 points/cycle
. With a buffer of 512 points, you will get 11.6 cycles of the sine wave in the buffer. Non-integer cycles lead to leakage.Before getting into this, though, try setting
wantedHz = 12*44100.0/512
to give exactly 12 cycles in the buffer. You should see two spikes in the transform: one at index 12, and one at index 511-12.The reason you'll see two spikes is that the transform of
sin(w_0*x)
isj*{-delta(w-w_0) - delta(w+w_0)}
. That is, you get an impulse function at w_0 and -w_0 in the imaginary part of the transform. The reason they are at the places they are is that the transform goes from 0 to 2*pi.After you do this, go back to
wantedH = 1000
, giving you a non-integer number of cycles in the buffer. You should see a wide tent-shaped result, centered around bins 11 and 511-11. You should multiplydataStream
by a window function (Hann is good) to reduce the impact of this effect.我也一直在与这个库作斗争,这个代码可以帮助你测试。这是我在互联网上阅读的代码的混合,看看将其包含在项目中是否会有趣。工作正常。它也将原始信号、FFT 和逆 FFT 的波形和值写入一个文件,以进行测试。它是用VS2010编译的
}
I have been fighting with this library too, and this code could help you to test. It´s a mixing of code that I read in Internet to see if It could be interesting to include in a project. Works Fine. It writes a file with the waveform and values of the original signal, FFT and the inverse FFT too just to test. It was compiled with VS2010
}