简体   繁体   English

16位短(实际)跨步数据的FFT

[英]FFT of 16 bit short (real) strided data

I need to compute the FFT of 2 arrays of short data stored like this (replicated millons of times): 我需要计算这样存储的2个短数据阵列的FFT(复制毫秒次): 内存中的数据分布 and so on. 等等。

The array values are represented by yellow and blue. 数组值由黄色和蓝色表示。 Every K values there is a size K space of unused data I need to skip. 每个K值都有一个我需要跳过的未使用数据的K空间。

I've reordered (and float-casted) the data to get rid of the useless values and used FFTW (with c) to compute the desired transform. 我重新排序(并浮动)数据以摆脱无用的值并使用FFTW(用c)来计算所需的变换。

I have two questions regarding this process. 关于这个过程我有两个问题。

  1. Is there a way to use the in , istride and idist parameters(as seen in the documentation ) to use the array as is (without reordering, only casted to float )? 有没有办法使用inistrideidist参数(如文档中所示 )按原样使用数组(没有重新排序,只能转换为浮点数)? I think there's not but maybe I'm burned out. 我想没有,但也许我已经烧光了。
  2. Is there any good library that could calculate the fft using short data as input? 是否有任何好的库可以使用短数据作为输入来计算fft? I'll be happy trading some precision for significant speedup. 我会很高兴交易一些精确的加速。 This code will run on an i7. 此代码将在i7上运行。

I am a very satisfied user of KISS FFT by Mark Borgerding. 我是Mark Borgerding对KISS FFT非常满意的用户。 It has an integer transform, and it also has a real-only transform that leverages the Hermitian symmetry inherent in the transform of an exclusively real-valued input to reduce the number of computations required. 它具有整数变换,并且它还具有纯实变换,该变换利用专有实值输入变换中固有的Hermitian对称性来减少所需的计算次数。

However, you will need to keep track of the data locations yourself. 但是,您需要自己跟踪数据位置。 The interface is extremely simple and just takes a pointer to an internal data buffer, and input and output buffer addresses. 该接口非常简单,只需一个指向内部数据缓冲区以及输入和输出缓冲区地址的指针。

Assuming your inputs are real-valued, you could do something like: 假设您的输入是实值的,您可以执行以下操作:

//Must compile with -DFIXED_POINT=16 directive,
//to tell kiss_fft to do fixed-point transforms with short int data

#include "kiss_fft.h"
#include "kiss_fftr.h"

const size_t K = ...;
const size_t inSize = K/6; //6 based on your diagram above, adjust as needed

kiss_fft_scalar *inBuf = bigInputBuffer;
kiss_fft_cpx outBuf[1+inSize/2]; //Hermitian symmetry, so DC + N/2 complex outputs
//kiss_fft_cpx outBuf[inSize]; //if not using the real transform
size_t ctr = 0;

kiss_fftr_cfg fftCfg = kiss_fftr_alloc(inSize, false, NULL, NULL);
//kiss_fft_cfg fftCfg = kiss_fft_alloc(inSize, false, NULL, NULL); //if not using the real transform

do {
  kiss_fftr(fftCfg, inBuf, outBuf); //kiss_fft(...) is not using the real transform
  //do something with outBuf
  ++ctr;
  if (ctr == 6) {
    inBuf += K;
    ctr = 0;
  } else {
    inBuf += K/6;
  }
} while ((inBuf - bigInputBuffer) < bigBufSize);

Caveats: 注意事项:

  • You need to recompile to change the data type. 您需要重新编译才能更改数据类型。 Use FIXED_POINT=16 or FIXED_POINT=32 for short or int data, or don't set FIXED_POINT to do floating-point transforms. 对于short或int数据,请使用FIXED_POINT=16FIXED_POINT=32 ,或者不要将FIXED_POINT设置为执行浮点变换。
  • FIXED_POINT must have the same value in your source, kiss_fft.* and kiss_fftr.* . FIXED_POINT在源中必须具有相同的值, FIXED_POINT kiss_fft.*kiss_fftr.* So either set it by hand in all files or (better) use -D to pass it as a compiler directive eg, clang -DFIXED_POINT=16 kiss_fft.c kiss_fftr.c main.c 所以要么在所有文件中手动设置,要么(更好)使用-D将其作为编译器指令传递,例如, clang -DFIXED_POINT=16 kiss_fft.c kiss_fftr.c main.c
  • The real transform expects the input buffer size to be even. 实数转换期望输入缓冲区大小为偶数。
  • The transform expects the input buffer to have a size that is a product of 2,3,5. 转换期望输入缓冲区的大小为2,3,5的乘积。 I don't remember if it works with other sizes, but even if it does it will be slow. 我不记得它是否适用于其他尺寸,但即使这样做也会很慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM