Fast Fourier Transform
Fast Fourier Transform (hereafter referred to FFT) is a fast algorithm for Discrete Fourier Transform (hereinafter referred to DFT), which is one of the most basic methods in the analysis of time-domain a frequency-domain transform.
The algorithm enables interconversion of data from the time domain to the frequency domain, which provides another dimension of data processing method support.
In engineering practices, DFT algorithms cannot be widely implemented in reality due to the computationally excessive.
The FFT algorithm optimizes the computation to a practicable order of magnitude by improving the computing method of the DFT, and the discrete Fourier transform is really widely used in the engineering field.
Operator Effect
| Time Domain Input Data | Parameter | Frequency Domain Output Data |
|---|
 | p_size = HB_HPL_FFT16 normalize = 0 dataType = HB_HPL_DATA_TYPE_I16 imFormat = HB_IM_FORMAT_SEPARATE numDimensionSize = 1 |  |
Principle
FFT is an improved method based on the DFT algorithm, which is equivalent to DFT in terms of computational results and optimizes the computational process.
If F(n) is the discrete Fourier transform of f(n), the DFT formula is expressed as follows:
F(n)=k=0∑N−1f(k)WNkn,n=0,1,⋯,N−1
The rotation factor is WNkn=e−jN2πkn , and N is the input sequence length.
IDFT is the inverse of DFT which is expressed as follows:
f(n)=N1k=0∑N−1F(k)WN−kn,n=0,1,⋯,N−1
Another fundamental formula is Euler's formula:
eix=cos(x)+i∗sin(x)
From Euler's formula is deduced that the rotation factor has the following properties:
WN0=e−jN2π0=e−j0=cos(0)+jsin(0)=1
WNk2N=(cos(−π)+jsin(−π))k=(−1)k
WN2kn=ej(2N2π)kn=W2Nkn
For the N-point DFT formula, the formula can be decomposed in parity order as follows:
F(n)=k=0∑N−1f(k)WNkn=E+O
E=k=0∑2N−1f(2k)e2N−j2πkn
O=WNnk=0∑2N−1f(2k+1)e2N−j2πkn
The decomposition effect is shown in the figure, bisecting the overall computational task layer by layer.
As shown above, the FFT tasks can all be decomposed into single-point computational tasks when N is a power of two.
From Euler's formula, WNn can be written in the following form, which shows that WNn has a periodicity and symmetry associated with N.
WNn=e−jN2πn=cos(−N2πn)+i∗sin(−N2πn)=cos(N2πn)−i∗sin(N2πn)
According to this property one obtains WNn=WN2N+n , where n takes the range [0,N/2) .
Taking the FFT operation with N of 8 as an example, the specific decomposition process as follows:
- Split 8 points into 4 points
- Split 4 points into 2 points
- Calculate the single-point FFT
In which, the computational process of interleaving the nodes two by two is known as butterfly operation as follows:
The specific formula as follows:
FN/4′(0)=fN(0)+WN/40∗fN(4)
FN/4′(1)=fN(0)−WN/40∗fN(4)
In the above figure, it can be seen that there is a bit-reversal relationship between F(n) and f(n) for n.
That is, in FFT, the indices of the input and output parameters are bit-reversals of each other,providing better support for optimized computational efficiency.
The calculation process of IFFT is similar to that of FFT, which can be derived based on the IDFT formula.
API Interface
int32_t hbFFT1D(hbUCPTaskHandle_t *taskHandle, hbHPLImaginaryData *dst,
hbHPLImaginaryData const *src, hbHPLFFTParam const *param);
For detailed interface information, please refer to hbFFT1D.
Usage
// Include the header
#include "hobot/hb_ucp.h"
#include "hobot/hpl/hb_hpl.h"
#include "hobot/hpl/hb_fft.h"
// init, allocate memory for data
src_length = 1024 * 1024 * 5;
hbUCPMallocCached(&src_re_mem, src_length, 0);
hbUCPMallocCached(&src_im_mem, src_length, 0);
hbHPLImaginaryData src;
src.realDataVirAddr = src_re_mem.virAddr;
src.realDataPhyAddr = src_re_mem.phyAddr;
src.imDataVirAddr = src_im_mem.virAddr;
src.imDataPhyAddr = src_im_mem.phyAddr;
src.numDimensionSize = 1;
src.dataType = HB_HPL_DATA_TYPE_I16;
src.imFormat = HB_IM_FORMAT_SEPARATE;
src.dimensionSize[0] = 16 * 11;
hbUCPMallocCached(&dst_re_mem, src_length, 0);
hbUCPMallocCached(&dst_im_mem, src_length, 0);
hbHPLImaginaryData dst;
dst.realDataVirAddr = dst_re_mem.virAddr;
dst.realDataPhyAddr = dst_re_mem.phyAddr;
dst.imDataVirAddr = dst_im_mem.virAddr;
dst.imDataPhyAddr = dst_im_mem.phyAddr;
dst.numDimensionSize = 1;
dst.dataType = HB_HPL_DATA_TYPE_I16;
dst.imFormat = HB_IM_FORMAT_SEPARATE;
dst.dimensionSize[0] = 16 * 11;
// init param
hbFFTParam param;
param.pSize = HB_FFT_POINT_SIZE_16;
param.normalize = 0;
// init task handle and schedule param
hbUCPTaskHandle_t task_handle{nullptr};
hbUCPSchedParam sched_param;
HB_UCP_INITIALIZE_SCHED_PARAM(&sched_param);
sched_param.backend = HB_UCP_DSP_CORE_0;
// create task
hbFFT1D(&task_handle, &dst, &src, ¶m);
// submit task
hbUCPSubmitTask(task_handle, &sched_param);
// wait for task done
hbUCPWaitTaskDone(task_handle, 0);
// release task handle
hbUCPReleaseTask(task_handle);
// release memory
hbUCPFree(&src_re_mem);
hbUCPFree(&src_im_mem);
hbUCPFree(&dst_re_mem);
hbUCPFree(&dst_im_mem);