Starting from API version 26.0.0, support for Fast Fourier Transform (FFT) and Inverse Fast Fourier Transform (IFFT) features has been introduced.
In Digital Signal Processing (DSP), FFT efficiently converts real-valued time-domain signals into frequency-domain representations, while IFFT restores frequency-domain signals back to the time domain. You can use these APIs to perform spectrum analysis, frequency-domain filtering, or signal reconstruction on audio signals, sensor data, or other time-series data.
Both FFT and IFFT functions offer single-precision (float) and double-precision (double) data type APIs, utilizing efficient algorithms to perform transformations between the time and frequency domains. The maximum supported number of FFT points is 2^16 (that is, 65,536 points). Note: The length of the input signal must be equal to 2^log2n, where log2n is a parameter specified during configuration creation.
FFT and IFFT are applicable to the following typical scenarios:
| API | Description |
|---|---|
| FAST_ErrorCode HMS_FAST_FFT_CreateConfig (FAST_FFTConfig** config, uint32_t log2n) | Creates a single-precision FFT configuration object. log2n is the base-2 logarithm of the number of FFT points and must satisfy 0 < log2n <= FAST_MAX_FFT_LOG2N (that is, 1 to 16). |
| FAST_ErrorCode HMS_FAST_FFT_CreateConfigD (FAST_FFTConfig** config, uint32_t log2n) | Creates a double-precision FFT configuration object. log2n is the base-2 logarithm of the number of FFT points and must satisfy 0 < log2n <= FAST_MAX_FFT_LOG2N (that is, 1 to 16). |
| void HMS_FAST_FFT_DestroyConfig (FAST_FFTConfig* config) | Destroys the FFT configuration and releases resources. |
| API | Description |
|---|---|
| FAST_ErrorCode HMS_FAST_FFT_ForwardTransform (FAST_FFTConfig* config, uint32_t length, const float input[], float outputRe[], float outputIm[]) | Computes the DFT of a single-precision, real-valued time-domain signal. |
| FAST_ErrorCode HMS_FAST_FFT_ForwardTransformD (FAST_FFTConfig* config, uint32_t length, const double input[], double outputRe[], double outputIm[]) | Computes the DFT of a double-precision, real-valued time-domain signal. |
| API | Description |
|---|---|
| FAST_ErrorCode HMS_FAST_FFT_InverseTransform (FAST_FFTConfig* config, uint32_t length, const float inputRe[], const float inputIm[], float output[]) | Computes the inverse DFT of a single-precision, complex-valued frequency-domain sequence. |
| FAST_ErrorCode HMS_FAST_FFT_InverseTransformD (FAST_FFTConfig* config, uint32_t length, const double inputRe[], const double inputIm[], double output[]) | Computes the inverse DFT of a double-precision, complex-valued frequency-domain sequence. |
This section uses the single-precision API for forward FFT computation as an example. (The single-precision API has no suffix, while the double-precision API has the suffix D.)
Link the related dynamic library in the CMake script.
find_library(
lib_fast_dsp
NAMES fast_dsp
)
target_link_libraries(entry PRIVATE ${lib_fast_dsp}) Call HMS_FAST_FFT_CreateConfig (single-precision) or HMS_FAST_FFT_CreateConfigD (double-precision) to create an FFT configuration instance (FAST_FFTConfig).
Allocate the input and output arrays based on the FFT size.
Call HMS_FAST_FFT_ForwardTransform/HMS_FAST_FFT_ForwardTransformD to compute FFT, or call HMS_FAST_FFT_InverseTransform/HMS_FAST_FFT_InverseTransformD to calculate IFFT.
Call HMS_FAST_FFT_DestroyConfig to destroy the FFT configuration instance and release internal resources.
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include "FASTKit/fast_dsp_transform.h"
FAST_ErrorCode fft_single_precision_demo() {
const uint32_t log2n = 4; // FFT size N = 16
const uint32_t length = 1 << log2n;
const uint32_t freq_size = length / 2 + 1;
FAST_FFTConfig *config = nullptr;
float *input = nullptr;
float *freqRe = nullptr;
float *freqIm = nullptr;
float *output = nullptr;
FAST_ErrorCode ret = FAST_ERROR_CODE_SUCCESS;
do {
// Create a configuration instance.
ret = HMS_FAST_FFT_CreateConfig(&config, log2n);
if (ret != FAST_ERROR_CODE_SUCCESS) {
printf("CreateConfig failed: %d\n", ret);
break; // If the operation fails, exit and go to the final cleanup area.
}
// Allocate memory.
input = (float *)malloc(length * sizeof(float));
freqRe = (float *)malloc(freq_size * sizeof(float));
freqIm = (float *)malloc(freq_size * sizeof(float));
output = (float *)malloc(length * sizeof(float));
// Check the allocation result.
if (!input || !freqRe || !freqIm || !output) {
printf("Memory allocation failed!\n");
ret = FAST_ERROR_CODE_FAIL;
break;
}
// Initialize data.
for (uint32_t i = 0; i < length; ++i) input[i] = (float)i;
// Forward FFT: time domain -> frequency domain.
ret = HMS_FAST_FFT_ForwardTransform(config, length, input, freqRe, freqIm);
if (ret == FAST_ERROR_CODE_SUCCESS) {
// Print the FFT computation result.
printf("Frequency domain (first 5 bins):\n");
for (uint32_t i = 0; i < 5 && i < freq_size; ++i) {
printf(" Bin %u: (%.4f, %.4fi)\n", i, freqRe[i], freqIm[i]);
}
} else {
printf("ForwardTransform failed: %d\n", ret);
break;
}
// Inverse FFT: frequency domain -> time domain
ret = HMS_FAST_FFT_InverseTransform(config, length, freqRe, freqIm, output);
if (ret == FAST_ERROR_CODE_SUCCESS) {
// Print the IFFT computation result.
printf("Reconstruction (normalized):\n Original: ");
for (uint32_t i = 0; i < length; ++i) printf("%.4f ", input[i]);
printf("\n Recovered: ");
for (uint32_t i = 0; i < length; ++i) printf("%.4f ", output[i]);
printf("\n");
} else {
printf("InverseTransform failed: %d\n", ret);
break;
}
} while (0);
if (input) free(input);
if (freqRe) free(freqRe);
if (freqIm) free(freqIm);
if (output) free(output);
if (config) HMS_FAST_FFT_DestroyConfig(config);
return ret;
} #include <cstdio>
#include <cstdlib>
#include <cmath>
#include "FASTKit/fast_dsp_transform.h"
FAST_ErrorCode fft_double_precision_demo() {
const uint32_t log2n = 4; // FFT size N = 16
const uint32_t length = 1 << log2n;
const uint32_t freq_size = length / 2 + 1;
FAST_FFTConfig *config = nullptr;
double *input = nullptr;
double *freqRe = nullptr;
double *freqIm = nullptr;
double *output = nullptr;
FAST_ErrorCode ret = FAST_ERROR_CODE_SUCCESS;
do {
// Create a configuration instance.
ret = HMS_FAST_FFT_CreateConfigD(&config, log2n);
if (ret != FAST_ERROR_CODE_SUCCESS) {
printf("CreateConfig failed: %d\n", ret);
break; // If the operation fails, exit and go to the final cleanup area.
}
// Allocate memory.
input = (double *)malloc(length * sizeof(double));
freqRe = (double *)malloc(freq_size * sizeof(double));
freqIm = (double *)malloc(freq_size * sizeof(double));
output = (double *)malloc(length * sizeof(double));
// Check the allocation result.
if (!input || !freqRe || !freqIm || !output) {
printf("Memory allocation failed!\n");
ret = FAST_ERROR_CODE_FAIL;
break;
}
// Initialize data.
for (uint32_t i = 0; i < length; ++i) input[i] = (double)i;
// Forward FFT: time domain -> frequency domain.
ret = HMS_FAST_FFT_ForwardTransformD(config, length, input, freqRe, freqIm);
if (ret == FAST_ERROR_CODE_SUCCESS) {
// Print the FFT computation result.
printf("Frequency domain (first 5 bins):\n");
for (uint32_t i = 0; i < 5 && i < freq_size; ++i) {
printf(" Bin %u: (%.4f, %.4fi)\n", i, freqRe[i], freqIm[i]);
}
} else {
printf("ForwardTransform failed: %d\n", ret);
break;
}
// Inverse FFT: frequency domain -> time domain
ret = HMS_FAST_FFT_InverseTransformD(config, length, freqRe, freqIm, output);
if (ret == FAST_ERROR_CODE_SUCCESS) {
// Print the IFFT computation result.
printf("Reconstruction (normalized):\n Original: ");
for (uint32_t i = 0; i < length; ++i) printf("%.4f ", input[i]);
printf("\n Recovered: ");
for (uint32_t i = 0; i < length; ++i) printf("%.4f ", output[i]);
printf("\n");
} else {
printf("InverseTransform failed: %d\n", ret);
break;
}
} while (0);
if (input) free(input);
if (freqRe) free(freqRe);
if (freqIm) free(freqIm);
if (output) free(output);
if (config) HMS_FAST_FFT_DestroyConfig(config);
return ret;
} FFT size limit: log2n must be between 1 and 16, meaning the FFT size N ranges from 2 to 65536.
Input length matching: The input lengths of the forward and inverse transforms must be the same as the log2n specified during configuration creation (length = 2^log2n).
Output array size: For the FFT with real-valued input, the output array size is length/2+1 because the spectrum of a real-valued signal has conjugate symmetry.
Memory management: After using the FFT configuration, call HMS_FAST_FFT_DestroyConfig to release resources.
Precision selection: The single-precision version features faster computing speed, while the double-precision version features higher precision. Select an appropriate version according to the application scenario.
Thread safety: In a multithreaded environment, multiple threads must not operate on the same FAST_FFTConfig configuration object at the same time. This includes concurrent calls to HMS_FAST_FFT_ForwardTransform (forward transform), HMS_FAST_FFT_InverseTransform (inverse transform), and their corresponding double-precision APIs. To ensure stable computation in a multithreaded environment, use one of the following approaches: