Преглед изворни кода

fix: fft库进行格式化

zengshuai пре 5 месеци
родитељ
комит
793b778dda

+ 565 - 161
components/fft/binding/luat_lib_fft.c

@@ -21,16 +21,20 @@
 #include "luat_log.h"
 
 #include "luat_conf_bsp.h"
-#include "rotable2.h"
 #include "luat_zbuff.h"
+#include "rotable2.h"
 // Q15 内核头文件(当前版本已实现)
 #include "fft_core_q15.h"
 
 // helper: read float array from lua table (1-based)
-static int read_lua_array_float(lua_State* L, int idx, float* out, int n) {
+static int read_lua_array_float(lua_State* L, int idx, float* out, int n)
+{
     for (int i = 0; i < n; i++) {
-        lua_rawgeti(L, idx, i+1);
-        if (!lua_isnumber(L, -1)) { lua_pop(L, 1); return -1; }
+        lua_rawgeti(L, idx, i + 1);
+        if (!lua_isnumber(L, -1)) {
+            lua_pop(L, 1);
+            return -1;
+        }
         out[i] = (float)lua_tonumber(L, -1);
         lua_pop(L, 1);
     }
@@ -38,11 +42,12 @@ static int read_lua_array_float(lua_State* L, int idx, float* out, int n) {
 }
 
 // helper: write float array into lua table (1-based)
-static void write_lua_array_float(lua_State* L, float* a, int n) {
+static void write_lua_array_float(lua_State* L, float* a, int n)
+{
     lua_createtable(L, n, 0);
     for (int i = 0; i < n; i++) {
         lua_pushnumber(L, a[i]);
-        lua_rawseti(L, -2, i+1);
+        lua_rawseti(L, -2, i + 1);
     }
 }
 
@@ -55,18 +60,22 @@ static void write_lua_array_float(lua_State* L, float* a, int n) {
 local N = 2048
 local Wc, Ws = fft.generate_twiddles(N)
 */
-static int l_fft_generate_twiddles(lua_State* L) {
+static int l_fft_generate_twiddles(lua_State* L)
+{
     int N = luaL_checkinteger(L, 1);
-    if (N <= 1 || (N & (N-1))) return luaL_error(L, "N must be power of 2");
-    int half = N/2;
-    float* Wc = luat_heap_malloc(sizeof(float)*half);
-    float* Ws = luat_heap_malloc(sizeof(float)*half);
+    if (N <= 1 || (N & (N - 1)))
+        return luaL_error(L, "N must be power of 2");
+    int half = N / 2;
+    float* Wc = luat_heap_malloc(sizeof(float) * half);
+    float* Ws = luat_heap_malloc(sizeof(float) * half);
     if (!Wc || !Ws) {
-        if (Wc) luat_heap_free(Wc);
-        if (Ws) luat_heap_free(Ws);
+        if (Wc)
+            luat_heap_free(Wc);
+        if (Ws)
+            luat_heap_free(Ws);
         return luaL_error(L, "no memory");
     }
-    fft_generate_twiddles(N, Wc, Ws);
+    luat_fft_generate_twiddles(N, Wc, Ws);
     write_lua_array_float(L, Wc, half);
     write_lua_array_float(L, Ws, half);
     luat_heap_free(Wc);
@@ -89,51 +98,86 @@ local Wc_q15 = zbuff.create((N//2)*2)
 local Ws_q15 = zbuff.create((N//2)*2)
 fft.generate_twiddles_q15_to_zbuff(N, Wc_q15, Ws_q15)
 */
-static int l_fft_generate_twiddles_q15_to_zbuff(lua_State* L) {
+static int l_fft_generate_twiddles_q15_to_zbuff(lua_State* L)
+{
     // 使用整型查表(度数,1度分辨率,缩放256)生成近似Q15旋转因子
     static const int16_t SIN_TABLE256[91] = {
-        0,4,9,13,18,22,27,31,36,40,44,49,53,58,62,66,71,75,79,83,
-        88,92,96,100,104,108,112,116,120,124,128,132,136,139,143,147,150,154,158,161,
-        165,168,171,175,178,181,184,187,190,193,196,199,202,204,207,210,212,215,217,219,
-        222,224,226,228,230,232,234,236,237,239,241,242,243,245,246,247,248,249,250,251,
-        252,253,254,254,255,255,255,256,256,256,256
+        0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 44, 49, 53, 58, 62, 66, 71, 75, 79, 83,
+        88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 139, 143, 147, 150, 154, 158, 161,
+        165, 168, 171, 175, 178, 181, 184, 187, 190, 193, 196, 199, 202, 204, 207, 210, 212, 215, 217, 219,
+        222, 224, 226, 228, 230, 232, 234, 236, 237, 239, 241, 242, 243, 245, 246, 247, 248, 249, 250, 251,
+        252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 256
     };
     int N = luaL_checkinteger(L, 1);
-    if (N <= 1 || (N & (N-1))) return luaL_error(L, "N 必须为 2 的幂");
+    if (N <= 1 || (N & (N - 1)))
+        return luaL_error(L, "N 必须为 2 的幂");
     luat_zbuff_t* zbWc = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
     luat_zbuff_t* zbWs = (luat_zbuff_t*)luaL_testudata(L, 3, LUAT_ZBUFF_TYPE);
-    if (!zbWc || !zbWs) return luaL_error(L, "Wc/Ws 需为 zbuff");
-    int need = (N/2) * 2;
-    if ((int)zbWc->len < need || (int)zbWs->len < need) return luaL_error(L, "zbuff 太小");
+    if (!zbWc || !zbWs)
+        return luaL_error(L, "Wc/Ws 需为 zbuff");
+    int need = (N / 2) * 2;
+    if ((int)zbWc->len < need || (int)zbWs->len < need)
+        return luaL_error(L, "zbuff 太小");
     int16_t* Wc = (int16_t*)zbWc->addr;
     int16_t* Ws = (int16_t*)zbWs->addr;
-    for (int k = 0; k < N/2; k++) {
+    for (int k = 0; k < N / 2; k++) {
         // angle = 360 * k / N (度),四舍五入
-        int deg = (int)((int64_t)k * 360 + (N/2)) / N;
+        int deg = (int)((int64_t)k * 360 + (N / 2)) / N;
         // cos 与 -sin,放大到 Q15(256<<7=32768,钳到 32767)
         int s256;
         int d = deg;
         int neg = 0;
-        if (d < 0) { d = -d + 180; }
+        if (d < 0) {
+            d = -d + 180;
+        }
         d %= 360;
-        if (d >= 180) { d -= 180; neg = 1; }
-        if (d <= 90) s256 = SIN_TABLE256[d]; else s256 = SIN_TABLE256[180 - d];
+        if (d >= 180) {
+            d -= 180;
+            neg = 1;
+        }
+        if (d <= 90)
+            s256 = SIN_TABLE256[d];
+        else
+            s256 = SIN_TABLE256[180 - d];
         int c256 = 0; // cos = sin(deg+90)
         int d2 = deg + 90;
-        neg = 0; d = d2;
-        if (d < 0) { d = -d + 180; }
+        neg = 0;
+        d = d2;
+        if (d < 0) {
+            d = -d + 180;
+        }
         d %= 360;
-        if (d >= 180) { d -= 180; neg = 1; }
-        if (d <= 90) c256 = SIN_TABLE256[d]; else c256 = SIN_TABLE256[180 - d];
-        if (neg) c256 = -c256;
+        if (d >= 180) {
+            d -= 180;
+            neg = 1;
+        }
+        if (d <= 90)
+            c256 = SIN_TABLE256[d];
+        else
+            c256 = SIN_TABLE256[180 - d];
+        if (neg)
+            c256 = -c256;
         int32_t wc = (int32_t)c256 << 7;
-        if (wc > 32767) wc = 32767; if (wc < -32768) wc = -32768;
+        if (wc > 32767)
+            wc = 32767;
+        if (wc < -32768)
+            wc = -32768;
         // -sin:复用 s256 并加符号
-        int sgn = 0; d = deg;
-        if (d < 0) { d = -d + 180; }
-        d %= 360; if (d >= 180) { d -= 180; sgn = 1; }
+        int sgn = 0;
+        d = deg;
+        if (d < 0) {
+            d = -d + 180;
+        }
+        d %= 360;
+        if (d >= 180) {
+            d -= 180;
+            sgn = 1;
+        }
         int32_t ws = (int32_t)(sgn ? -s256 : s256) << 7;
-        if (ws > 32767) ws = 32767; if (ws < -32768) ws = -32768;
+        if (ws > 32767)
+            ws = 32767;
+        if (ws < -32768)
+            ws = -32768;
         Wc[k] = (int16_t)wc;
         Ws[k] = (int16_t)ws;
     }
@@ -177,37 +221,116 @@ fft.generate_twiddles_q15_to_zbuff(N, Wc_q15, Ws_q15)
 -- 写入 U12 数据到 real_i16 后:
 fft.run(real_i16, imag_i16, N, Wc_q15, Ws_q15, {core="q15", input_format="u12"})
 */
-static int l_fft_run(lua_State* L) {
+static int l_fft_run(lua_State* L)
+{
     int N = luaL_checkinteger(L, 3);
-    if (N <= 1 || (N & (N-1))) return luaL_error(L, "N 必须为 2 的幂");
+    if (N <= 1 || (N & (N - 1)))
+        return luaL_error(L, "N 必须为 2 的幂");
 
     float *r = NULL, *im = NULL, *Wc = NULL, *Ws = NULL;
     int r_free = 0, im_free = 0, wc_free = 0, ws_free = 0;
 
     // 可选参数解析(opts):当前版本仅支持 core/input_format(其余项作为未来优化)
-    const char* core = "f32";         // "f32" | "q15"
+    const char* core = "f32"; // "f32" | "q15"
     const char* input_format = "f32"; // "f32"|"u12"|"u16"|"s16"
 
     // real
     luat_zbuff_t* zb = (luat_zbuff_t*)luaL_testudata(L, 1, LUAT_ZBUFF_TYPE);
-    if (zb) { r = (float*)zb->addr; }
-    else { r = luat_heap_malloc(sizeof(float)*N); r_free = 1; if (!r) return luaL_error(L, "no memory"); if (read_lua_array_float(L, 1, r, N)) { if (r_free) luat_heap_free(r); return luaL_error(L, "real must be number array or zbuff"); } }
+    if (zb) {
+        r = (float*)zb->addr;
+    } else {
+        r = luat_heap_malloc(sizeof(float) * N);
+        r_free = 1;
+        if (!r)
+            return luaL_error(L, "no memory");
+        if (read_lua_array_float(L, 1, r, N)) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "real must be number array or zbuff");
+        }
+    }
     // imag
     zb = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
-    if (zb) { im = (float*)zb->addr; }
-    else { im = luat_heap_malloc(sizeof(float)*N); im_free = 1; if (!im) { if (r_free) luat_heap_free(r); return luaL_error(L, "no memory"); } if (read_lua_array_float(L, 2, im, N)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); return luaL_error(L, "imag must be number array or zbuff"); } }
+    if (zb) {
+        im = (float*)zb->addr;
+    } else {
+        im = luat_heap_malloc(sizeof(float) * N);
+        im_free = 1;
+        if (!im) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "no memory");
+        }
+        if (read_lua_array_float(L, 2, im, N)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            return luaL_error(L, "imag must be number array or zbuff");
+        }
+    }
     // W_real
     zb = (luat_zbuff_t*)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE);
-    if (zb) { Wc = (float*)zb->addr; }
-    else { Wc = luat_heap_malloc(sizeof(float)*(N/2)); wc_free = 1; if (!Wc) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); return luaL_error(L, "no memory"); } if (read_lua_array_float(L, 4, Wc, N/2)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); return luaL_error(L, "W_real must be number array or zbuff"); } }
+    if (zb) {
+        Wc = (float*)zb->addr;
+    } else {
+        Wc = luat_heap_malloc(sizeof(float) * (N / 2));
+        wc_free = 1;
+        if (!Wc) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            return luaL_error(L, "no memory");
+        }
+        if (read_lua_array_float(L, 4, Wc, N / 2)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            return luaL_error(L, "W_real must be number array or zbuff");
+        }
+    }
     // W_imag
     zb = (luat_zbuff_t*)luaL_testudata(L, 5, LUAT_ZBUFF_TYPE);
-    if (zb) { Ws = (float*)zb->addr; }
-    else { Ws = luat_heap_malloc(sizeof(float)*(N/2)); ws_free = 1; if (!Ws) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); return luaL_error(L, "内存不足"); } if (read_lua_array_float(L, 5, Ws, N/2)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws); return luaL_error(L, "W_imag 需为数字数组或 zbuff"); } }
+    if (zb) {
+        Ws = (float*)zb->addr;
+    } else {
+        Ws = luat_heap_malloc(sizeof(float) * (N / 2));
+        ws_free = 1;
+        if (!Ws) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            return luaL_error(L, "内存不足");
+        }
+        if (read_lua_array_float(L, 5, Ws, N / 2)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
+            return luaL_error(L, "W_imag 需为数字数组或 zbuff");
+        }
+    }
     // 读取第6个参数的 opts(若有)
     if (lua_gettop(L) >= 6 && lua_istable(L, 6)) {
-        lua_getfield(L, 6, "core"); if (!lua_isnil(L, -1)) core = luaL_checkstring(L, -1); lua_pop(L, 1);
-        lua_getfield(L, 6, "input_format"); if (!lua_isnil(L, -1)) input_format = luaL_checkstring(L, -1); lua_pop(L, 1);
+        lua_getfield(L, 6, "core");
+        if (!lua_isnil(L, -1))
+            core = luaL_checkstring(L, -1);
+        lua_pop(L, 1);
+        lua_getfield(L, 6, "input_format");
+        if (!lua_isnil(L, -1))
+            input_format = luaL_checkstring(L, -1);
+        lua_pop(L, 1);
     }
 
     // 如果选择 q15 内核,且输入为整数 zbuff,则走 q15 路径
@@ -218,37 +341,63 @@ static int l_fft_run(lua_State* L) {
         luat_zbuff_t* zb_real = (luat_zbuff_t*)luaL_testudata(L, 1, LUAT_ZBUFF_TYPE);
         luat_zbuff_t* zb_imag = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
         if (!zb_real) {
-            if (r_free) luat_heap_free(r);
-            if (im_free) luat_heap_free(im);
-            if (wc_free) luat_heap_free(Wc);
-            if (ws_free) luat_heap_free(Ws);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "q15 模式要求 real 为整数 zbuff");
         }
         if ((int)zb_real->len < N * 2) {
-            if (r_free) luat_heap_free(r);
-            if (im_free) luat_heap_free(im);
-            if (wc_free) luat_heap_free(Wc);
-            if (ws_free) luat_heap_free(Ws);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "real zbuff 太小");
         }
         // 原地:将整数输入就地转换为带符号 Q15(覆盖 zbuff)
         uint16_t* r16 = (uint16_t*)zb_real->addr;
         for (int i = 0; i < N; i++) {
-            int32_t v; uint16_t u = r16[i];
-            if (strcmp(input_format, "u12") == 0) { v = (int32_t)(u & 0x0FFF) - 2048; v <<= 4; }
-            else if (strcmp(input_format, "u16") == 0) { v = (int32_t)u - 32768; }
-            else { v = (int16_t)u; }
-            if (v > 32767) v = 32767; if (v < -32768) v = -32768;
+            int32_t v;
+            uint16_t u = r16[i];
+            if (strcmp(input_format, "u12") == 0) {
+                v = (int32_t)(u & 0x0FFF) - 2048;
+                v <<= 4;
+            } else if (strcmp(input_format, "u16") == 0) {
+                v = (int32_t)u - 32768;
+            } else {
+                v = (int16_t)u;
+            }
+            if (v > 32767)
+                v = 32767;
+            if (v < -32768)
+                v = -32768;
             ((int16_t*)zb_real->addr)[i] = (int16_t)v;
         }
-        if (zb_imag && (int)zb_imag->len >= N*2) {
+        if (zb_imag && (int)zb_imag->len >= N * 2) {
             uint16_t* i16 = (uint16_t*)zb_imag->addr;
             for (int i = 0; i < N; i++) {
-                int32_t v; uint16_t u = i16[i];
-                if (strcmp(input_format, "u12") == 0) { v = (int32_t)(u & 0x0FFF) - 2048; v <<= 4; }
-                else if (strcmp(input_format, "u16") == 0) { v = (int32_t)u - 32768; }
-                else { v = (int16_t)u; }
-                if (v > 32767) v = 32767; if (v < -32768) v = -32768;
+                int32_t v;
+                uint16_t u = i16[i];
+                if (strcmp(input_format, "u12") == 0) {
+                    v = (int32_t)(u & 0x0FFF) - 2048;
+                    v <<= 4;
+                } else if (strcmp(input_format, "u16") == 0) {
+                    v = (int32_t)u - 32768;
+                } else {
+                    v = (int16_t)u;
+                }
+                if (v > 32767)
+                    v = 32767;
+                if (v < -32768)
+                    v = -32768;
                 ((int16_t*)zb_imag->addr)[i] = (int16_t)v;
             }
         } else if (zb_imag) {
@@ -259,32 +408,62 @@ static int l_fft_run(lua_State* L) {
         // 强制要求外部传入 Q15 twiddle
         luat_zbuff_t* zbWc = (luat_zbuff_t*)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE);
         luat_zbuff_t* zbWs = (luat_zbuff_t*)luaL_testudata(L, 5, LUAT_ZBUFF_TYPE);
-        const int need_tw = (N/2) * 2;
+        const int need_tw = (N / 2) * 2;
         if (!(zbWc && zbWs) || (int)zbWc->len < need_tw || (int)zbWs->len < need_tw) {
-            if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "q15 需传入 Wc/Ws zbuff,长度 N/2*2 字节");
         }
 
         int scale_exp = 0;
-        int rc = fft_inplace_q15((int16_t*)zb_real->addr, zb_imag ? (int16_t*)zb_imag->addr : NULL,
-                                  N, 0, (const int16_t*)zbWc->addr, (const int16_t*)zbWs->addr,
-                                  0, &scale_exp);
-        if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws);
-        if (rc != 0) return luaL_error(L, "q15 内核执行失败");
+        int rc = luat_fft_inplace_q15((int16_t*)zb_real->addr, zb_imag ? (int16_t*)zb_imag->addr : NULL,
+                                       N, 0, (const int16_t*)zbWc->addr, (const int16_t*)zbWs->addr,
+                                       0, &scale_exp);
+        if (r_free)
+            luat_heap_free(r);
+        if (im_free)
+            luat_heap_free(im);
+        if (wc_free)
+            luat_heap_free(Wc);
+        if (ws_free)
+            luat_heap_free(Ws);
+        if (rc != 0)
+            return luaL_error(L, "q15 内核执行失败");
         return 0;
     }
 
     // 默认:沿用 float32 路径
-    fft_run_inplace(r, im, N, Wc, Ws);
+    luat_fft_run_inplace(r, im, N, Wc, Ws);
 
     // if input was table, write back
-    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) { lua_settop(L, 2); for (int i = 0; i < N; i++) { lua_pushnumber(L, r[i]); lua_rawseti(L, 1, i+1); } }
-    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) { for (int i = 0; i < N; i++) { lua_pushnumber(L, im[i]); lua_rawseti(L, 2, i+1); } }
+    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) {
+        lua_settop(L, 2);
+        for (int i = 0; i < N; i++) {
+            lua_pushnumber(L, r[i]);
+            lua_rawseti(L, 1, i + 1);
+        }
+    }
+    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) {
+        for (int i = 0; i < N; i++) {
+            lua_pushnumber(L, im[i]);
+            lua_rawseti(L, 2, i + 1);
+        }
+    }
 
-    if (r_free) luat_heap_free(r);
-    if (im_free) luat_heap_free(im);
-    if (wc_free) luat_heap_free(Wc);
-    if (ws_free) luat_heap_free(Ws);
+    if (r_free)
+        luat_heap_free(r);
+    if (im_free)
+        luat_heap_free(im);
+    if (wc_free)
+        luat_heap_free(Wc);
+    if (ws_free)
+        luat_heap_free(Ws);
     return 0;
 }
 
@@ -301,27 +480,111 @@ static int l_fft_run(lua_State* L) {
  - input_format: "f32" | "u12" | "u16" | "s16"(q15 时必填其一)
 @return nil 就地修改 real/imag,并在 f32 路径下包含 1/N 归一化
 */
-static int l_fft_ifft(lua_State* L) {
+static int l_fft_ifft(lua_State* L)
+{
     int N = luaL_checkinteger(L, 3);
-    if (N <= 1 || (N & (N-1))) return luaL_error(L, "N 必须为 2 的幂");
+    if (N <= 1 || (N & (N - 1)))
+        return luaL_error(L, "N 必须为 2 的幂");
 
     float *r = NULL, *im = NULL, *Wc = NULL, *Ws = NULL;
     int r_free = 0, im_free = 0, wc_free = 0, ws_free = 0;
     // 可选 opts(同 run):当前仅 core/input_format
-    const char* core = "f32"; const char* input_format = "f32";
+    const char* core = "f32";
+    const char* input_format = "f32";
     luat_zbuff_t* zb = NULL;
     zb = (luat_zbuff_t*)luaL_testudata(L, 1, LUAT_ZBUFF_TYPE);
-    if (zb) { r = (float*)zb->addr; } else { r = luat_heap_malloc(sizeof(float)*N); r_free = 1; if (!r) return luaL_error(L, "no memory"); if (read_lua_array_float(L, 1, r, N)) { if (r_free) luat_heap_free(r); return luaL_error(L, "real must be number array or zbuff"); } }
+    if (zb) {
+        r = (float*)zb->addr;
+    } else {
+        r = luat_heap_malloc(sizeof(float) * N);
+        r_free = 1;
+        if (!r)
+            return luaL_error(L, "no memory");
+        if (read_lua_array_float(L, 1, r, N)) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "real must be number array or zbuff");
+        }
+    }
     zb = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
-    if (zb) { im = (float*)zb->addr; } else { im = luat_heap_malloc(sizeof(float)*N); im_free = 1; if (!im) { if (r_free) luat_heap_free(r); return luaL_error(L, "no memory"); } if (read_lua_array_float(L, 2, im, N)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); return luaL_error(L, "imag must be number array or zbuff"); } }
+    if (zb) {
+        im = (float*)zb->addr;
+    } else {
+        im = luat_heap_malloc(sizeof(float) * N);
+        im_free = 1;
+        if (!im) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "no memory");
+        }
+        if (read_lua_array_float(L, 2, im, N)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            return luaL_error(L, "imag must be number array or zbuff");
+        }
+    }
     zb = (luat_zbuff_t*)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE);
-    if (zb) { Wc = (float*)zb->addr; } else { Wc = luat_heap_malloc(sizeof(float)*(N/2)); wc_free = 1; if (!Wc) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); return luaL_error(L, "no memory"); } if (read_lua_array_float(L, 4, Wc, N/2)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); return luaL_error(L, "W_real must be number array or zbuff"); } }
+    if (zb) {
+        Wc = (float*)zb->addr;
+    } else {
+        Wc = luat_heap_malloc(sizeof(float) * (N / 2));
+        wc_free = 1;
+        if (!Wc) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            return luaL_error(L, "no memory");
+        }
+        if (read_lua_array_float(L, 4, Wc, N / 2)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            return luaL_error(L, "W_real must be number array or zbuff");
+        }
+    }
     zb = (luat_zbuff_t*)luaL_testudata(L, 5, LUAT_ZBUFF_TYPE);
-    if (zb) { Ws = (float*)zb->addr; } else { Ws = luat_heap_malloc(sizeof(float)*(N/2)); ws_free = 1; if (!Ws) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); return luaL_error(L, "内存不足"); } if (read_lua_array_float(L, 5, Ws, N/2)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws); return luaL_error(L, "W_imag 需为数字数组或 zbuff"); } }
+    if (zb) {
+        Ws = (float*)zb->addr;
+    } else {
+        Ws = luat_heap_malloc(sizeof(float) * (N / 2));
+        ws_free = 1;
+        if (!Ws) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            return luaL_error(L, "内存不足");
+        }
+        if (read_lua_array_float(L, 5, Ws, N / 2)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
+            return luaL_error(L, "W_imag 需为数字数组或 zbuff");
+        }
+    }
 
     if (lua_gettop(L) >= 6 && lua_istable(L, 6)) {
-        lua_getfield(L, 6, "core"); if (!lua_isnil(L, -1)) core = luaL_checkstring(L, -1); lua_pop(L, 1);
-        lua_getfield(L, 6, "input_format"); if (!lua_isnil(L, -1)) input_format = luaL_checkstring(L, -1); lua_pop(L, 1);
+        lua_getfield(L, 6, "core");
+        if (!lua_isnil(L, -1))
+            core = luaL_checkstring(L, -1);
+        lua_pop(L, 1);
+        lua_getfield(L, 6, "input_format");
+        if (!lua_isnil(L, -1))
+            input_format = luaL_checkstring(L, -1);
+        lua_pop(L, 1);
     }
 
     int use_q15 = (core && strcmp(core, "q15") == 0);
@@ -330,89 +593,186 @@ static int l_fft_ifft(lua_State* L) {
         luat_zbuff_t* zb_real = (luat_zbuff_t*)luaL_testudata(L, 1, LUAT_ZBUFF_TYPE);
         luat_zbuff_t* zb_imag = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
         if (!zb_real) {
-            if (r_free) luat_heap_free(r);
-            if (im_free) luat_heap_free(im);
-            if (wc_free) luat_heap_free(Wc);
-            if (ws_free) luat_heap_free(Ws);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "q15 模式要求 real 为整数 zbuff");
         }
         if ((int)zb_real->len < N * 2) {
-            if (r_free) luat_heap_free(r);
-            if (im_free) luat_heap_free(im);
-            if (wc_free) luat_heap_free(Wc);
-            if (ws_free) luat_heap_free(Ws);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "real zbuff 太小");
         }
 
         int16_t* rq = (int16_t*)luat_heap_malloc(sizeof(int16_t) * N);
         int16_t* iq = (int16_t*)luat_heap_malloc(sizeof(int16_t) * N);
         if (!rq || !iq) {
-            if (rq) luat_heap_free(rq); if (iq) luat_heap_free(iq);
-            if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im);
-            if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws);
+            if (rq)
+                luat_heap_free(rq);
+            if (iq)
+                luat_heap_free(iq);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
             return luaL_error(L, "内存不足");
         }
 
         const uint16_t* r16 = (const uint16_t*)zb_real->addr;
         for (int i = 0; i < N; i++) {
-            int32_t v; uint16_t u = r16[i];
-            if (strcmp(input_format, "u12") == 0) { v = ((int32_t)(u & 0x0FFF)) - 2048; v <<= 4; }
-            else if (strcmp(input_format, "u16") == 0) { v = (int32_t)u - 32768; }
-            else { v = (int16_t)u; }
-            if (v > 32767) v = 32767; if (v < -32768) v = -32768; rq[i] = (int16_t)v;
+            int32_t v;
+            uint16_t u = r16[i];
+            if (strcmp(input_format, "u12") == 0) {
+                v = ((int32_t)(u & 0x0FFF)) - 2048;
+                v <<= 4;
+            } else if (strcmp(input_format, "u16") == 0) {
+                v = (int32_t)u - 32768;
+            } else {
+                v = (int16_t)u;
+            }
+            if (v > 32767)
+                v = 32767;
+            if (v < -32768)
+                v = -32768;
+            rq[i] = (int16_t)v;
         }
         if (zb_imag && (int)zb_imag->len >= N * 2) {
             const uint16_t* i16 = (const uint16_t*)zb_imag->addr;
             for (int i = 0; i < N; i++) {
-                int32_t v; uint16_t u = i16[i];
-                if (strcmp(input_format, "u12") == 0) { v = ((int32_t)(u & 0x0FFF)) - 2048; v <<= 4; }
-                else if (strcmp(input_format, "u16") == 0) { v = (int32_t)u - 32768; }
-                else { v = (int16_t)u; }
-                if (v > 32767) v = 32767; if (v < -32768) v = -32768; iq[i] = (int16_t)v;
+                int32_t v;
+                uint16_t u = i16[i];
+                if (strcmp(input_format, "u12") == 0) {
+                    v = ((int32_t)(u & 0x0FFF)) - 2048;
+                    v <<= 4;
+                } else if (strcmp(input_format, "u16") == 0) {
+                    v = (int32_t)u - 32768;
+                } else {
+                    v = (int16_t)u;
+                }
+                if (v > 32767)
+                    v = 32767;
+                if (v < -32768)
+                    v = -32768;
+                iq[i] = (int16_t)v;
             }
-        } else { memset(iq, 0, sizeof(int16_t) * N); }
+        } else {
+            memset(iq, 0, sizeof(int16_t) * N);
+        }
 
         // 使用传入的 Q15 旋转因子(zbuff)或按需生成
         luat_zbuff_t* zbWc = (luat_zbuff_t*)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE);
         luat_zbuff_t* zbWs = (luat_zbuff_t*)luaL_testudata(L, 5, LUAT_ZBUFF_TYPE);
-        const int need_tw = (N/2) * 2;
-        const int16_t* Wcq = NULL; const int16_t* Wsq = NULL;
-        int16_t* Wcq_alloc = NULL; int16_t* Wsq_alloc = NULL;
+        const int need_tw = (N / 2) * 2;
+        const int16_t* Wcq = NULL;
+        const int16_t* Wsq = NULL;
+        int16_t* Wcq_alloc = NULL;
+        int16_t* Wsq_alloc = NULL;
         if (zbWc && zbWs && (int)zbWc->len >= need_tw && (int)zbWs->len >= need_tw) {
             Wcq = (const int16_t*)zbWc->addr;
             Wsq = (const int16_t*)zbWs->addr;
         } else {
-            Wcq_alloc = (int16_t*)luat_heap_malloc(sizeof(int16_t) * (N/2));
-            Wsq_alloc = (int16_t*)luat_heap_malloc(sizeof(int16_t) * (N/2));
-            if (!Wcq_alloc || !Wsq_alloc) { if (Wcq_alloc) luat_heap_free(Wcq_alloc); if (Wsq_alloc) luat_heap_free(Wsq_alloc); luat_heap_free(rq); luat_heap_free(iq);
-                if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws); return luaL_error(L, "内存不足"); }
-            fft_generate_twiddles_q15(Wcq_alloc, Wsq_alloc, N);
-            Wcq = Wcq_alloc; Wsq = Wsq_alloc;
+            Wcq_alloc = (int16_t*)luat_heap_malloc(sizeof(int16_t) * (N / 2));
+            Wsq_alloc = (int16_t*)luat_heap_malloc(sizeof(int16_t) * (N / 2));
+            if (!Wcq_alloc || !Wsq_alloc) {
+                if (Wcq_alloc)
+                    luat_heap_free(Wcq_alloc);
+                if (Wsq_alloc)
+                    luat_heap_free(Wsq_alloc);
+                luat_heap_free(rq);
+                luat_heap_free(iq);
+                if (r_free)
+                    luat_heap_free(r);
+                if (im_free)
+                    luat_heap_free(im);
+                if (wc_free)
+                    luat_heap_free(Wc);
+                if (ws_free)
+                    luat_heap_free(Ws);
+                return luaL_error(L, "内存不足");
+            }
+            luat_fft_generate_twiddles_q15(Wcq_alloc, Wsq_alloc, N);
+            Wcq = Wcq_alloc;
+            Wsq = Wsq_alloc;
         }
 
         int scale_exp = 0;
-        int rc = fft_inplace_q15(rq, iq, N, 1, Wcq, Wsq, 0, &scale_exp); // inverse=1
-        if (Wcq_alloc) luat_heap_free(Wcq_alloc);
-        if (Wsq_alloc) luat_heap_free(Wsq_alloc);
-        if (rc != 0) { luat_heap_free(rq); luat_heap_free(iq);
-            if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws); return luaL_error(L, "q15 内核执行失败"); }
-
-        for (int i = 0; i < N; i++) ((int16_t*)zb_real->addr)[i] = rq[i];
-        if (zb_imag && (int)zb_imag->len >= N * 2) { for (int i = 0; i < N; i++) ((int16_t*)zb_imag->addr)[i] = iq[i]; }
-        luat_heap_free(rq); luat_heap_free(iq);
-        if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); if (wc_free) luat_heap_free(Wc); if (ws_free) luat_heap_free(Ws);
+        int rc = luat_fft_inplace_q15(rq, iq, N, 1, Wcq, Wsq, 0, &scale_exp); // inverse=1
+        if (Wcq_alloc)
+            luat_heap_free(Wcq_alloc);
+        if (Wsq_alloc)
+            luat_heap_free(Wsq_alloc);
+        if (rc != 0) {
+            luat_heap_free(rq);
+            luat_heap_free(iq);
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            if (wc_free)
+                luat_heap_free(Wc);
+            if (ws_free)
+                luat_heap_free(Ws);
+            return luaL_error(L, "q15 内核执行失败");
+        }
+
+        for (int i = 0; i < N; i++)
+            ((int16_t*)zb_real->addr)[i] = rq[i];
+        if (zb_imag && (int)zb_imag->len >= N * 2) {
+            for (int i = 0; i < N; i++)
+                ((int16_t*)zb_imag->addr)[i] = iq[i];
+        }
+        luat_heap_free(rq);
+        luat_heap_free(iq);
+        if (r_free)
+            luat_heap_free(r);
+        if (im_free)
+            luat_heap_free(im);
+        if (wc_free)
+            luat_heap_free(Wc);
+        if (ws_free)
+            luat_heap_free(Ws);
         return 0;
     }
 
-    ifft_run_inplace(r, im, N, Wc, Ws);
+    luat_ifft_run_inplace(r, im, N, Wc, Ws);
 
-    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) { lua_settop(L, 2); for (int i = 0; i < N; i++) { lua_pushnumber(L, r[i]); lua_rawseti(L, 1, i+1); } }
-    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) { for (int i = 0; i < N; i++) { lua_pushnumber(L, im[i]); lua_rawseti(L, 2, i+1); } }
+    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) {
+        lua_settop(L, 2);
+        for (int i = 0; i < N; i++) {
+            lua_pushnumber(L, r[i]);
+            lua_rawseti(L, 1, i + 1);
+        }
+    }
+    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) {
+        for (int i = 0; i < N; i++) {
+            lua_pushnumber(L, im[i]);
+            lua_rawseti(L, 2, i + 1);
+        }
+    }
 
-    if (r_free) luat_heap_free(r);
-    if (im_free) luat_heap_free(im);
-    if (wc_free) luat_heap_free(Wc);
-    if (ws_free) luat_heap_free(Ws);
+    if (r_free)
+        luat_heap_free(r);
+    if (im_free)
+        luat_heap_free(im);
+    if (wc_free)
+        luat_heap_free(Wc);
+    if (ws_free)
+        luat_heap_free(Ws);
     return 0;
 }
 
@@ -428,36 +788,80 @@ static int l_fft_ifft(lua_State* L) {
 -- 先完成 FFT 得到谱 (real, imag),再调用积分:
 fft.fft_integral(real, imag, N, fs/N)
 */
-static int l_fft_integral(lua_State* L) {
+static int l_fft_integral(lua_State* L)
+{
     int n = luaL_checkinteger(L, 3);
     float df = (float)luaL_checknumber(L, 4);
-    if (n <= 1 || (n & (n-1))) return luaL_error(L, "n must be power of 2");
-    float *r = NULL, *im = NULL; int r_free = 0, im_free = 0;
+    if (n <= 1 || (n & (n - 1)))
+        return luaL_error(L, "n must be power of 2");
+    float *r = NULL, *im = NULL;
+    int r_free = 0, im_free = 0;
     luat_zbuff_t* zb = NULL;
     zb = (luat_zbuff_t*)luaL_testudata(L, 1, LUAT_ZBUFF_TYPE);
-    if (zb) { r = (float*)zb->addr; } else { r = luat_heap_malloc(sizeof(float)*n); r_free = 1; if (!r) return luaL_error(L, "no memory"); if (read_lua_array_float(L, 1, r, n)) { if (r_free) luat_heap_free(r); return luaL_error(L, "real must be number array or zbuff"); } }
+    if (zb) {
+        r = (float*)zb->addr;
+    } else {
+        r = luat_heap_malloc(sizeof(float) * n);
+        r_free = 1;
+        if (!r)
+            return luaL_error(L, "no memory");
+        if (read_lua_array_float(L, 1, r, n)) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "real must be number array or zbuff");
+        }
+    }
     zb = (luat_zbuff_t*)luaL_testudata(L, 2, LUAT_ZBUFF_TYPE);
-    if (zb) { im = (float*)zb->addr; } else { im = luat_heap_malloc(sizeof(float)*n); im_free = 1; if (!im) { if (r_free) luat_heap_free(r); return luaL_error(L, "no memory"); } if (read_lua_array_float(L, 2, im, n)) { if (r_free) luat_heap_free(r); if (im_free) luat_heap_free(im); return luaL_error(L, "imag must be number array or zbuff"); } }
-    fft_integral_inplace(r, im, n, df);
-    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) { lua_settop(L, 2); for (int i = 0; i < n; i++) { lua_pushnumber(L, r[i]); lua_rawseti(L, 1, i+1); } }
-    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) { for (int i = 0; i < n; i++) { lua_pushnumber(L, im[i]); lua_rawseti(L, 2, i+1); } }
-    if (r_free) luat_heap_free(r);
-    if (im_free) luat_heap_free(im);
+    if (zb) {
+        im = (float*)zb->addr;
+    } else {
+        im = luat_heap_malloc(sizeof(float) * n);
+        im_free = 1;
+        if (!im) {
+            if (r_free)
+                luat_heap_free(r);
+            return luaL_error(L, "no memory");
+        }
+        if (read_lua_array_float(L, 2, im, n)) {
+            if (r_free)
+                luat_heap_free(r);
+            if (im_free)
+                luat_heap_free(im);
+            return luaL_error(L, "imag must be number array or zbuff");
+        }
+    }
+    luat_fft_integral_inplace(r, im, n, df);
+    if (!luaL_testudata(L, 1, LUAT_ZBUFF_TYPE)) {
+        lua_settop(L, 2);
+        for (int i = 0; i < n; i++) {
+            lua_pushnumber(L, r[i]);
+            lua_rawseti(L, 1, i + 1);
+        }
+    }
+    if (!luaL_testudata(L, 2, LUAT_ZBUFF_TYPE)) {
+        for (int i = 0; i < n; i++) {
+            lua_pushnumber(L, im[i]);
+            lua_rawseti(L, 2, i + 1);
+        }
+    }
+    if (r_free)
+        luat_heap_free(r);
+    if (im_free)
+        luat_heap_free(im);
     return 0;
 }
 
 static const rotable_Reg_t reg_fft[] = {
-    {"generate_twiddles", ROREG_FUNC(l_fft_generate_twiddles)},
-    {"generate_twiddles_q15_to_zbuff", ROREG_FUNC(l_fft_generate_twiddles_q15_to_zbuff)},
-    {"run",               ROREG_FUNC(l_fft_run)},
-    {"ifft",              ROREG_FUNC(l_fft_ifft)},
-    {"fft_integral",      ROREG_FUNC(l_fft_integral)},
-    {NULL,                 ROREG_INT(0)}
+    { "generate_twiddles", ROREG_FUNC(l_fft_generate_twiddles) },
+    { "generate_twiddles_q15_to_zbuff", ROREG_FUNC(l_fft_generate_twiddles_q15_to_zbuff) },
+    { "run", ROREG_FUNC(l_fft_run) },
+    { "ifft", ROREG_FUNC(l_fft_ifft) },
+    { "fft_integral", ROREG_FUNC(l_fft_integral) },
+    { NULL, ROREG_INT(0) }
 };
 
-LUAMOD_API int luaopen_fft(lua_State *L) {
+LUAMOD_API int luaopen_fft(lua_State* L)
+{
     luat_newlib2(L, reg_fft);
     return 1;
 }
-
-

+ 6 - 9
components/fft/inc/fft_core.h

@@ -6,26 +6,23 @@
 extern "C" {
 #endif
 
-
 // Generate twiddle factors cos/sin for size N (N must be power of 2)
 // Wc and Ws must have length at least N/2 (float32)
-void fft_generate_twiddles(int N, float* Wc, float* Ws);
+void luat_fft_generate_twiddles(int N, float* Wc, float* Ws);
 
 // In-place iterative radix-2 FFT
 // If Wc/Ws are NULL, twiddles are computed on the fly
-void fft_run_inplace(float* real, float* imag, int N,
-                     const float* Wc, const float* Ws);
+void luat_fft_run_inplace(float* real, float* imag, int N,
+    const float* Wc, const float* Ws);
 
 // In-place IFFT with 1/N normalization
-void ifft_run_inplace(float* real, float* imag, int N,
-                      const float* Wc, const float* Ws);
+void luat_ifft_run_inplace(float* real, float* imag, int N,
+    const float* Wc, const float* Ws);
 
 // Frequency-domain integral: X(ω) -> X(ω)/(jω)
 // n is FFT size, df is frequency resolution fs/n
-void fft_integral_inplace(float* xr, float* xi, int n, float df);
+void luat_fft_integral_inplace(float* xr, float* xi, int n, float df);
 
 #ifdef __cplusplus
 }
 #endif
-
-

+ 4 - 6
components/fft/inc/fft_core_q15.h

@@ -10,7 +10,7 @@ extern "C" {
 // 生成 Q15 旋转因子表(长度 N/2):
 // Wc[k] = cos(2πk/N) 的 Q15 表示;
 // Ws[k] = -sin(2πk/N) 的 Q15 表示(前向FFT用负号)
-void fft_generate_twiddles_q15(int16_t* Wc, int16_t* Ws, int N);
+void luat_fft_generate_twiddles_q15(int16_t* Wc, int16_t* Ws, int N);
 
 // Q15 原地FFT/IFFT
 // 参数:
@@ -20,14 +20,12 @@ void fft_generate_twiddles_q15(int16_t* Wc, int16_t* Ws, int N);
 // - block_scaling_mode: 0=每级固定右移1位;1=条件缩放(按级最大值)
 // - out_scale_exp: 输出累计右移的位数(用于幅值/单位还原)
 // 返回:0 成功,<0 表示参数错误
-int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
-                    const int16_t* Wc, const int16_t* Ws,
-                    int block_scaling_mode, int* out_scale_exp);
+int luat_fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
+    const int16_t* Wc, const int16_t* Ws,
+    int block_scaling_mode, int* out_scale_exp);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // LUAT_FFT_CORE_Q15_H
-
-

+ 63 - 49
components/fft/src/fft_core.c

@@ -1,17 +1,18 @@
 #include "fft_core.h"
 #include "luat_base.h"
 #include <math.h>
-#include <string.h>
 #include <stdint.h>
+#include <string.h>
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
 #endif
 
 #ifndef __USER_FUNC_IN_RAM__
-#define __USER_FUNC_IN_RAM__ 
+#define __USER_FUNC_IN_RAM__
 #endif
 
-__USER_FUNC_IN_RAM__ static inline int reverse_bits(int x, int bits) {
+__USER_FUNC_IN_RAM__ static inline int reverse_bits(int x, int bits)
+{
     int y = 0;
     for (int i = 0; i < bits; i++) {
         y = (y << 1) | (x & 1);
@@ -20,8 +21,9 @@ __USER_FUNC_IN_RAM__ static inline int reverse_bits(int x, int bits) {
     return y;
 }
 
-__USER_FUNC_IN_RAM__ void fft_generate_twiddles(int N, float* Wc, float* Ws) {
-    for (int k = 0; k < N/2; k++) {
+__USER_FUNC_IN_RAM__ void luat_fft_generate_twiddles(int N, float* Wc, float* Ws)
+{
+    for (int k = 0; k < N / 2; k++) {
         float angle = (float)(-2.0 * M_PI * (double)k / (double)N);
         Wc[k] = (float)cos(angle);
         Ws[k] = (float)sin(angle);
@@ -29,35 +31,42 @@ __USER_FUNC_IN_RAM__ void fft_generate_twiddles(int N, float* Wc, float* Ws) {
 }
 
 __USER_FUNC_IN_RAM__ static void fft_inplace_core(float* real, float* imag, int N, int inverse,
-                             const float* Wc, const float* Ws) {
+    const float* Wc, const float* Ws)
+{
     // bit-reverse permutation 位逆序置换
     // 计算需要的位数来表示所有索引
-    int bits = 0; while ((1 << bits) < N) bits++;
-    
+    int bits = 0;
+    while ((1 << bits) < N)
+        bits++;
+
     // 对所有元素进行位逆序重排
     for (int i = 0; i < N; i++) {
-        int j = reverse_bits(i, bits);  // 获取位逆序后的索引
-        if (j > i) {  // 只交换一次,避免重复交换
+        int j = reverse_bits(i, bits); // 获取位逆序后的索引
+        if (j > i) { // 只交换一次,避免重复交换
             // 交换实部
-            float tr = real[i]; real[i] = real[j]; real[j] = tr;
+            float tr = real[i];
+            real[i] = real[j];
+            real[j] = tr;
             // 交换虚部
-            float ti = imag[i]; imag[i] = imag[j]; imag[j] = ti;
+            float ti = imag[i];
+            imag[i] = imag[j];
+            imag[j] = ti;
         }
     }
 
     // iterative stages 迭代阶段 - Cooley-Tukey算法的主要循环
     // len从2开始,每次翻倍,直到N
     for (int len = 2; len <= N; len <<= 1) {
-        int half = len >> 1;           // 当前阶段的半长度
-        int step = N / len;            // twiddle step 旋转因子步长
-        
+        int half = len >> 1; // 当前阶段的半长度
+        int step = N / len; // twiddle step 旋转因子步长
+
         // 处理每个长度为len的子序列
         for (int i = 0; i < N; i += len) {
             // 对当前子序列进行蝶形运算
             for (int j = 0; j < half; j++) {
-                int idx = j * step;    // 旋转因子索引
-                float wr, wi;          // 旋转因子的实部和虚部
-                
+                int idx = j * step; // 旋转因子索引
+                float wr, wi; // 旋转因子的实部和虚部
+
                 // 获取旋转因子
                 if (Wc && Ws) {
                     // 使用预计算的旋转因子表
@@ -69,39 +78,42 @@ __USER_FUNC_IN_RAM__ static void fft_inplace_core(float* real, float* imag, int
                     wr = (float)cos(angle);
                     wi = (float)sin(angle);
                 }
-                
+
                 // 如果是逆变换,需要共轭旋转因子
-                if (inverse) wi = -wi;
-                
+                if (inverse)
+                    wi = -wi;
+
                 // 蝶形运算的两个数据点索引
-                int p = i + j;         // 上半部分索引
-                int q = p + half;      // 下半部分索引
-                
+                int p = i + j; // 上半部分索引
+                int q = p + half; // 下半部分索引
+
                 // 计算旋转后的值:W * X[q]
-                float tr = wr * real[q] - wi * imag[q];  // 复数乘法实部
-                float ti = wr * imag[q] + wi * real[q];  // 复数乘法虚部
-                
+                float tr = wr * real[q] - wi * imag[q]; // 复数乘法实部
+                float ti = wr * imag[q] + wi * real[q]; // 复数乘法虚部
+
                 // 保存原始值
                 float ur = real[p];
                 float ui = imag[p];
-                
+
                 // 蝶形运算:更新两个数据点
-                real[p] = ur + tr;     // X[p] = X[p] + W*X[q]
+                real[p] = ur + tr; // X[p] = X[p] + W*X[q]
                 imag[p] = ui + ti;
-                real[q] = ur - tr;     // X[q] = X[p] - W*X[q]
+                real[q] = ur - tr; // X[q] = X[p] - W*X[q]
                 imag[q] = ui - ti;
             }
         }
     }
 }
 
-__USER_FUNC_IN_RAM__ void fft_run_inplace(float* real, float* imag, int N,
-                     const float* Wc, const float* Ws) {
+__USER_FUNC_IN_RAM__ void luat_fft_run_inplace(float* real, float* imag, int N,
+    const float* Wc, const float* Ws)
+{
     fft_inplace_core(real, imag, N, 0, Wc, Ws);
 }
 
-__USER_FUNC_IN_RAM__ void ifft_run_inplace(float* real, float* imag, int N,
-                      const float* Wc, const float* Ws) {
+__USER_FUNC_IN_RAM__ void luat_ifft_run_inplace(float* real, float* imag, int N,
+    const float* Wc, const float* Ws)
+{
     fft_inplace_core(real, imag, N, 1, Wc, Ws);
     // 1/N normalization
     float invN = (float)(1.0 / (double)N);
@@ -111,30 +123,32 @@ __USER_FUNC_IN_RAM__ void ifft_run_inplace(float* real, float* imag, int N,
     }
 }
 
-__USER_FUNC_IN_RAM__ void fft_integral_inplace(float* xr, float* xi, int n, float df) {
+__USER_FUNC_IN_RAM__ void luat_fft_integral_inplace(float* xr, float* xi, int n, float df)
+{
     // 计算角频率步长 Calculate angular frequency step
     const float two_pi_df = (float)(2.0 * M_PI) * df;
-    
+
     // positive freqs (exclude DC) 正频率部分(排除直流分量)
     // 处理正频率分量,通过除以jω实现时域积分
-    for (int i = 1; i < n/2; i++) {
+    for (int i = 1; i < n / 2; i++) {
         float omega = two_pi_df * (float)i; // 当前频率的角频率
         if (omega != 0.0) {
             // 保存原始值
             float xr0 = xr[i];
             float xi0 = xi[i];
             // 执行 X(ω) / (jω) = (xr + j*xi) / (j*ω) = xi/ω - j*xr/ω
-            xr[i] =  xi0 / omega;  // 实部:xi/ω
-            xi[i] = -xr0 / omega;  // 虚部:-xr/ω
+            xr[i] = xi0 / omega; // 实部:xi/ω
+            xi[i] = -xr0 / omega; // 虚部:-xr/ω
         } else {
             // 频率为0时设为0(避免除零)
-            xr[i] = 0.0; xi[i] = 0.0;
+            xr[i] = 0.0;
+            xi[i] = 0.0;
         }
     }
-    
+
     // negative freqs 负频率部分
     // 处理负频率分量
-    for (int i = n/2 + 1; i < n; i++) {
+    for (int i = n / 2 + 1; i < n; i++) {
         int k = i - n; // negative bin index 负频率索引
         float omega = two_pi_df * (float)k; // 负频率的角频率
         if (omega != 0.0) {
@@ -142,17 +156,17 @@ __USER_FUNC_IN_RAM__ void fft_integral_inplace(float* xr, float* xi, int n, floa
             float xr0 = xr[i];
             float xi0 = xi[i];
             // 执行 X(ω) / (jω) 变换
-            xr[i] =  xi0 / omega;  // 实部:xi/ω
-            xi[i] = -xr0 / omega;  // 虚部:-xr/ω
+            xr[i] = xi0 / omega; // 实部:xi/ω
+            xi[i] = -xr0 / omega; // 虚部:-xr/ω
         } else {
             // 频率为0时设为0(避免除零)
-            xr[i] = 0.0; xi[i] = 0.0;
+            xr[i] = 0.0;
+            xi[i] = 0.0;
         }
     }
-    
+
     // DC 直流分量
     // 直流分量(ω=0)在积分后应为0
-    xr[0] = 0.0; xi[0] = 0.0;
+    xr[0] = 0.0;
+    xi[0] = 0.0;
 }
-
-

+ 71 - 43
components/fft/src/fft_core_q15.c

@@ -1,41 +1,62 @@
 #include "fft_core_q15.h"
 // 去除浮点依赖
 
-static inline int16_t q15_saturate(int32_t x) {
-    if (x > 32767) return 32767;
-    if (x < -32768) return -32768;
+#ifndef __USER_FUNC_IN_RAM__
+#define __USER_FUNC_IN_RAM__
+#endif
+
+static inline int16_t q15_saturate(int32_t x)
+{
+    if (x > 32767)
+        return 32767;
+    if (x < -32768)
+        return -32768;
     return (int16_t)x;
 }
 
-static inline int16_t q15_mul(int16_t a, int16_t b) {
+static inline int16_t q15_mul(int16_t a, int16_t b)
+{
     int32_t t = (int32_t)a * (int32_t)b; // Q15*Q15 -> Q30
-    t += 1 << 14;                        // round
-    t >>= 15;                            // back to Q15
-    return (int16_t)t;                   // 饱和延后到写回
+    t += 1 << 14; // round
+    t >>= 15; // back to Q15
+    return (int16_t)t; // 饱和延后到写回
 }
 
 // 占位:不再提供浮点生成(使用绑定层的整型 LUT 生成)
-void fft_generate_twiddles_q15(int16_t* Wc, int16_t* Ws, int N) { (void)Wc; (void)Ws; (void)N; }
+__USER_FUNC_IN_RAM__ void luat_fft_generate_twiddles_q15(int16_t* Wc, int16_t* Ws, int N)
+{
+    (void)Wc;
+    (void)Ws;
+    (void)N;
+}
 
-int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
-                    const int16_t* Wc, const int16_t* Ws,
-                    int block_scaling_mode, int* out_scale_exp) {
+__USER_FUNC_IN_RAM__ int luat_fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
+    const int16_t* Wc, const int16_t* Ws,
+    int block_scaling_mode, int* out_scale_exp)
+{
     // 参数检查:验证输入指针和FFT大小的有效性
-    if (!real || !imag || !Wc || !Ws) return -1;
-    if (N <= 1 || (N & (N - 1))) return -2;  // N必须是2的幂
-    int scale_exp = 0;  // 记录总缩放指数
+    if (!real || !imag || !Wc || !Ws)
+        return -1;
+    if (N <= 1 || (N & (N - 1)))
+        return -2; // N必须是2的幂
+    int scale_exp = 0; // 记录总缩放指数
 
     // 位逆序重排(原地、迭代版本)
     // 对所有元素进行位逆序重排,为FFT算法做准备
     for (int i = 1, j = 0; i < N; i++) {
-        int bit = N >> 1;  // 从最高位开始
+        int bit = N >> 1; // 从最高位开始
         // 计算i的位逆序索引j
-        for (; j & bit; bit >>= 1) j &= ~bit;
+        for (; j & bit; bit >>= 1)
+            j &= ~bit;
         j |= bit;
         // 只交换一次,避免重复交换
         if (i < j) {
-            int16_t tr = real[i]; real[i] = real[j]; real[j] = tr;
-            int16_t ti = imag[i]; imag[i] = imag[j]; imag[j] = ti;
+            int16_t tr = real[i];
+            real[i] = real[j];
+            real[j] = tr;
+            int16_t ti = imag[i];
+            imag[i] = imag[j];
+            imag[j] = ti;
         }
     }
 
@@ -45,40 +66,40 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
     // FFT主循环:Cooley-Tukey算法的迭代实现
     // len从2开始,每次翻倍,直到N
     for (int len = 2; len <= N; len <<= 1) {
-        int half = len >> 1;          // 当前阶段的半长度
-        int step = N / len;           // 旋转因子的步长
+        int half = len >> 1; // 当前阶段的半长度
+        int step = N / len; // 旋转因子的步长
 
         int need_scale_this_stage = 0; // 本级是否需要缩放的标志
-        int32_t stage_max_abs = 0;     // 本级的最大绝对值
+        int32_t stage_max_abs = 0; // 本级的最大绝对值
 
         // 处理每个长度为len的子序列
         for (int base = 0; base < N; base += len) {
-            int idx = 0;  // 旋转因子索引
+            int idx = 0; // 旋转因子索引
             // 对当前子序列进行蝶形运算
             for (int j = 0; j < half; j++) {
                 // 获取旋转因子W = wr + i*wi
                 int16_t wr = Wc[idx];
-                int16_t wi = Ws[idx];  // 已按方向传入
+                int16_t wi = Ws[idx]; // 已按方向传入
                 idx += step;
 
                 // 蝶形运算的两个数据点索引
-                int p = base + j;      // 上半部分索引
-                int q = p + half;      // 下半部分索引
+                int p = base + j; // 上半部分索引
+                int q = p + half; // 下半部分索引
 
                 // 读取输入数据
-                int16_t ur = real[p];  // X[p]的实部
-                int16_t ui = imag[p];  // X[p]的虚部
-                int16_t vr = real[q];  // X[q]的实部
-                int16_t vi = imag[q];  // X[q]的虚部
+                int16_t ur = real[p]; // X[p]的实部
+                int16_t ui = imag[p]; // X[p]的虚部
+                int16_t vr = real[q]; // X[q]的实部
+                int16_t vi = imag[q]; // X[q]的虚部
 
                 // 计算旋转后的值:W * X[q] = (wr + i*wi) * (vr + i*vi)
                 int16_t tr = (int16_t)((int32_t)q15_mul(wr, vr) - (int32_t)q15_mul(wi, vi));
                 int16_t ti = (int16_t)((int32_t)q15_mul(wr, vi) + (int32_t)q15_mul(wi, vr));
 
                 // 蝶形运算:计算输出
-                int32_t xr = (int32_t)ur + (int32_t)tr;  // X[p] = X[p] + W*X[q]
+                int32_t xr = (int32_t)ur + (int32_t)tr; // X[p] = X[p] + W*X[q]
                 int32_t xi = (int32_t)ui + (int32_t)ti;
-                int32_t yr = (int32_t)ur - (int32_t)tr;  // X[q] = X[p] - W*X[q]
+                int32_t yr = (int32_t)ur - (int32_t)tr; // X[q] = X[p] - W*X[q]
                 int32_t yi = (int32_t)ui - (int32_t)ti;
 
                 if (block_scaling_mode == 1) {
@@ -87,10 +108,14 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
                     int32_t a1 = xi < 0 ? -xi : xi;
                     int32_t a2 = yr < 0 ? -yr : yr;
                     int32_t a3 = yi < 0 ? -yi : yi;
-                    if (a0 > stage_max_abs) stage_max_abs = a0;
-                    if (a1 > stage_max_abs) stage_max_abs = a1;
-                    if (a2 > stage_max_abs) stage_max_abs = a2;
-                    if (a3 > stage_max_abs) stage_max_abs = a3;
+                    if (a0 > stage_max_abs)
+                        stage_max_abs = a0;
+                    if (a1 > stage_max_abs)
+                        stage_max_abs = a1;
+                    if (a2 > stage_max_abs)
+                        stage_max_abs = a2;
+                    if (a3 > stage_max_abs)
+                        stage_max_abs = a3;
                     // 暂存到输出(先不缩放,避免重复计算)
                     real[p] = q15_saturate(xr);
                     imag[p] = q15_saturate(xi);
@@ -98,7 +123,10 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
                     imag[q] = q15_saturate(yi);
                 } else {
                     // 固定缩放模式:每级固定右移1位防止溢出
-                    xr >>= 1; xi >>= 1; yr >>= 1; yi >>= 1;
+                    xr >>= 1;
+                    xi >>= 1;
+                    yr >>= 1;
+                    yi >>= 1;
                     real[p] = q15_saturate(xr);
                     imag[p] = q15_saturate(xi);
                     real[q] = q15_saturate(yr);
@@ -110,7 +138,7 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
         if (block_scaling_mode == 1) {
             // 条件缩放:检查是否需要在本级进行缩放
             // 如果最大值接近Q15范围上限,则统一右移1位
-            if (stage_max_abs > 16384) {  // 16384 = 2^14,接近32767的一半
+            if (stage_max_abs > 16384) { // 16384 = 2^14,接近32767的一半
                 need_scale_this_stage = 1;
             }
             if (need_scale_this_stage) {
@@ -118,11 +146,12 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
                 for (int i = 0; i < N; i++) {
                     int32_t r = real[i];
                     int32_t im = imag[i];
-                    r >>= 1; im >>= 1;
+                    r >>= 1;
+                    im >>= 1;
                     real[i] = q15_saturate(r);
                     imag[i] = q15_saturate(im);
                 }
-                scale_exp += 1;  // 记录缩放次数
+                scale_exp += 1; // 记录缩放次数
             }
         } else {
             scale_exp += 1; // 固定缩放模式:每级缩放指数+1
@@ -130,8 +159,7 @@ int fft_inplace_q15(int16_t* real, int16_t* imag, int N, int inverse,
     }
 
     // 输出总缩放指数(用于后续的幅度校正)
-    if (out_scale_exp) *out_scale_exp = scale_exp;
-    return 0;  // 成功返回
+    if (out_scale_exp)
+        *out_scale_exp = scale_exp;
+    return 0; // 成功返回
 }
-
-