add some code
This commit is contained in:
292
managed_components/espressif__dl_fft/dl_fft.hpp
Normal file
292
managed_components/espressif__dl_fft/dl_fft.hpp
Normal file
@@ -0,0 +1,292 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "dl_fft.h"
|
||||
#include "dl_rfft.h"
|
||||
|
||||
namespace dl {
|
||||
class FFT {
|
||||
private:
|
||||
// Private constructor for singleton
|
||||
FFT() = default;
|
||||
~FFT() = default;
|
||||
|
||||
// Delete copy constructor and assignment operator
|
||||
FFT(const FFT &) = delete;
|
||||
FFT &operator=(const FFT &) = delete;
|
||||
|
||||
// Four handle vectors for different FFT types
|
||||
std::vector<dl_fft_f32_t *> fft_f32_handles;
|
||||
std::vector<dl_fft_s16_t *> fft_s16_handles;
|
||||
std::vector<dl_fft_f32_t *> rfft_f32_handles;
|
||||
std::vector<dl_fft_s16_t *> rfft_s16_handles;
|
||||
|
||||
// Mutex for thread safety (only used during handle initialization)
|
||||
std::mutex mutex_;
|
||||
|
||||
uint32_t m_caps = MALLOC_CAP_8BIT; // Default memory allocation capabilities
|
||||
|
||||
// Helper function to find or create handle
|
||||
template <typename HandleType, typename InitFunc>
|
||||
HandleType *get_or_create_handle(int fft_length, std::vector<HandleType *> &handles, InitFunc init_func)
|
||||
{
|
||||
// First check without lock (lock-free read)
|
||||
for (auto *handle : handles) {
|
||||
if (handle->fft_point == fft_length) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
// Lock only for handle creation
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// Double-check after acquiring lock (avoid race condition)
|
||||
for (auto *handle : handles) {
|
||||
if (handle->fft_point == fft_length) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new handle
|
||||
HandleType *new_handle = init_func(fft_length, m_caps); // 0 for default memory allocation
|
||||
if (new_handle) {
|
||||
handles.push_back(new_handle);
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
public:
|
||||
// Get singleton instance
|
||||
static FFT *get_instance()
|
||||
{
|
||||
static FFT instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
uint32_t get_caps() { return m_caps; }
|
||||
|
||||
void set_caps(uint32_t caps) { m_caps = caps; }
|
||||
|
||||
// FFT for float32
|
||||
esp_err_t fft(float *data, int fft_length)
|
||||
{
|
||||
dl_fft_f32_t *handle = get_or_create_handle(
|
||||
fft_length, fft_f32_handles, [](int len, uint32_t caps) { return dl_fft_f32_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return dl_fft_f32_run(handle, data);
|
||||
}
|
||||
|
||||
// IFFT for float32
|
||||
esp_err_t ifft(float *data, int fft_length)
|
||||
{
|
||||
dl_fft_f32_t *handle = get_or_create_handle(
|
||||
fft_length, fft_f32_handles, [](int len, uint32_t caps) { return dl_fft_f32_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return dl_ifft_f32_run(handle, data);
|
||||
}
|
||||
|
||||
// RFFT for float32
|
||||
esp_err_t rfft(float *data, int fft_length)
|
||||
{
|
||||
dl_fft_f32_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_f32_handles, [](int len, uint32_t caps) { return dl_rfft_f32_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return dl_rfft_f32_run(handle, data);
|
||||
}
|
||||
|
||||
// IRFFT for float32
|
||||
esp_err_t irfft(float *data, int fft_length)
|
||||
{
|
||||
dl_fft_f32_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_f32_handles, [](int len, uint32_t caps) { return dl_rfft_f32_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return dl_irfft_f32_run(handle, data);
|
||||
}
|
||||
|
||||
// FFT for int16
|
||||
esp_err_t fft(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, fft_s16_handles, [](int len, uint32_t caps) { return dl_fft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_fft_s16_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// IFFT for int16
|
||||
esp_err_t ifft(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, fft_s16_handles, [](int len, uint32_t caps) { return dl_fft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_ifft_s16_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// RFFT for int16
|
||||
esp_err_t rfft(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_s16_handles, [](int len, uint32_t caps) { return dl_rfft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_rfft_s16_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// IRFFT for int16
|
||||
esp_err_t irfft(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_s16_handles, [](int len, uint32_t caps) { return dl_rfft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_irfft_s16_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// FFT with high precision for int16
|
||||
esp_err_t fft_hp(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, fft_s16_handles, [](int len, uint32_t caps) { return dl_fft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_fft_s16_hp_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// IFFT with high precision for int16
|
||||
esp_err_t ifft_hp(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, fft_s16_handles, [](int len, uint32_t caps) { return dl_fft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_ifft_s16_hp_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// RFFT with high precision for int16
|
||||
esp_err_t rfft_hp(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_s16_handles, [](int len, uint32_t caps) { return dl_rfft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_rfft_s16_hp_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// IRFFT with high precision for int16
|
||||
esp_err_t irfft_hp(int16_t *data, int fft_length, int in_exponent = 0, int *out_exponent = nullptr)
|
||||
{
|
||||
dl_fft_s16_t *handle = get_or_create_handle(
|
||||
fft_length, rfft_s16_handles, [](int len, uint32_t caps) { return dl_rfft_s16_init(len, caps); });
|
||||
|
||||
if (!handle) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int temp_out_exp = 0;
|
||||
esp_err_t result = dl_irfft_s16_hp_run(handle, data, in_exponent, out_exponent ? out_exponent : &temp_out_exp);
|
||||
return result;
|
||||
}
|
||||
|
||||
// WARNING: This function is NOT thread-safe with respect to concurrent FFT operations.
|
||||
// It should only be called when no other FFT methods are running, as it will deinitialize all handles
|
||||
// and may cause undefined behavior if other threads are using FFT functions.
|
||||
// Ensure all FFT operations have completed before calling clear().
|
||||
void clear()
|
||||
{
|
||||
ESP_LOGW("FFT",
|
||||
"This function is NOT thread-safe. Ensure all FFT operations have completed before calling clear()");
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// Clear FFT float32 handles
|
||||
for (auto *handle : fft_f32_handles) {
|
||||
dl_fft_f32_deinit(handle);
|
||||
}
|
||||
fft_f32_handles.clear();
|
||||
std::vector<dl_fft_f32_t *>().swap(fft_f32_handles);
|
||||
|
||||
// Clear FFT int16 handles
|
||||
for (auto *handle : fft_s16_handles) {
|
||||
dl_fft_s16_deinit(handle);
|
||||
}
|
||||
fft_s16_handles.clear();
|
||||
std::vector<dl_fft_s16_t *>().swap(fft_s16_handles);
|
||||
|
||||
// Clear RFFT float32 handles
|
||||
for (auto *handle : rfft_f32_handles) {
|
||||
dl_rfft_f32_deinit(handle);
|
||||
}
|
||||
rfft_f32_handles.clear();
|
||||
std::vector<dl_fft_f32_t *>().swap(rfft_f32_handles);
|
||||
|
||||
// Clear RFFT int16 handles
|
||||
for (auto *handle : rfft_s16_handles) {
|
||||
dl_rfft_s16_deinit(handle);
|
||||
}
|
||||
rfft_s16_handles.clear();
|
||||
std::vector<dl_fft_s16_t *>().swap(rfft_s16_handles);
|
||||
}
|
||||
|
||||
// Get handle count for debugging
|
||||
size_t get_handle_count()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return fft_f32_handles.size() + fft_s16_handles.size() + rfft_f32_handles.size() + rfft_s16_handles.size();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dl
|
||||
Reference in New Issue
Block a user