You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改移动平均滤波器代码以适配可变频率信号?

问题描述

原本使用固定长度(100样本)的高效移动平均滤波器处理固定频率正弦波,代码如下:

static double test_sin = 0; 
static double sum_x = 0 , filter_out_X = 0 ;
static int LENGTH_X = 100 , counter_filter_X = 0 ;
static double Buffer_X[100]= {0} ;
// ... 省略其他代码
sum_x = sum_x + test_sin - Buffer_X[counter_filter_X];
filter_out_X = sum_x / LENGTH_X ;
Buffer_X[counter_filter_X] = (test_sin);
counter_filter_X = counter_filter_X+1 ;
if (counter_filter_X == LENGTH_X)
{
    counter_filter_X = 0 ;
}

现在需要适配可变频率正弦波,需根据所需样本数动态调整LENGTH_X和Buffer_X的长度,但静态数组长度无法修改。尝试通过条件初始化静态变量的方式解决,代码如下但无效:

if(freq>1000)
{
    static int LENGTH_X = 100 , counter_filter_X = 0 ;
    static double Buffer_X[100]= {0} ;
}
else
{
    static int LENGTH_X = 10 , counter_filter_X = 0 ;
    static double Buffer_X[10]= {0} ;
}

请问如何修改代码实现动态调整样本长度的需求?

解决方案

方法1:使用动态内存分配

将静态数组替换为动态分配的内存,通过变量记录当前缓冲区长度,当频率变化时重新分配内存并重置滤波器状态:

static double test_sin = 0; 
static double sum_x = 0, filter_out_X = 0;
static int current_length = 0, counter_filter_X = 0;
static double *Buffer_X = NULL;

// 根据频率计算目标长度
int target_length = (freq > 1000) ? 100 : 10;

// 目标长度变化时重新初始化
if (target_length != current_length) {
    // 释放旧内存
    if (Buffer_X != NULL) {
        free(Buffer_X);
        Buffer_X = NULL;
    }
    // 分配新内存并初始化
    Buffer_X = (double *)malloc(target_length * sizeof(double));
    if (Buffer_X != NULL) {
        memset(Buffer_X, 0, target_length * sizeof(double));
        current_length = target_length;
        sum_x = 0;
        counter_filter_X = 0;
    }
}

// 仅当缓冲区有效时执行滤波逻辑
if (Buffer_X != NULL) {
    sum_x = sum_x + test_sin - Buffer_X[counter_filter_X];
    filter_out_X = sum_x / current_length;
    Buffer_X[counter_filter_X] = test_sin;
    counter_filter_X++;
    if (counter_filter_X == current_length) {
        counter_filter_X = 0;
    }
}

注意:使用动态内存需确保程序退出前释放内存避免泄漏;嵌入式环境需确认系统支持malloc和free。

方法2:预先分配最大长度缓冲区

若频率对应的样本长度有明确上限(比如最大100、最小10),可直接创建最大长度的静态数组,通过current_length变量控制实际使用长度:

static double test_sin = 0; 
static double sum_x = 0, filter_out_X = 0;
static int current_length = 100, counter_filter_X = 0;
static double Buffer_X[100] = {0}; // 预先分配最大长度

// 根据频率更新当前长度
int target_length = (freq > 1000) ? 100 : 10;
if (target_length != current_length) {
    current_length = target_length;
    sum_x = 0;
    counter_filter_X = 0;
    // 重置缓冲区前current_length个元素为0
    memset(Buffer_X, 0, current_length * sizeof(double));
}

// 滤波核心逻辑
sum_x = sum_x + test_sin - Buffer_X[counter_filter_X];
filter_out_X = sum_x / current_length;
Buffer_X[counter_filter_X] = test_sin;
counter_filter_X++;
if (counter_filter_X == current_length) {
    counter_filter_X = 0;
}

该方法无需动态内存分配,适合嵌入式或内存分配受限场景,缺点是会占用最大长度的固定内存空间。

方法3:封装为结构体(模块化实现)

将滤波器状态变量封装为结构体,方便管理和复用,结合动态内存实现长度调整:

typedef struct {
    double sum;
    double *buffer;
    int current_length;
    int counter;
    double output;
} MovingAverageFilter;

static MovingAverageFilter ma_filter = {0};
static double test_sin = 0;

// 更新滤波器长度的函数
void update_ma_filter_length(int target_length) {
    if (ma_filter.current_length == target_length) return;

    // 释放旧缓冲区
    if (ma_filter.buffer != NULL) {
        free(ma_filter.buffer);
        ma_filter.buffer = NULL;
    }

    // 分配新缓冲区并初始化
    ma_filter.buffer = (double *)malloc(target_length * sizeof(double));
    if (ma_filter.buffer != NULL) {
        memset(ma_filter.buffer, 0, target_length * sizeof(double));
        ma_filter.current_length = target_length;
        ma_filter.sum = 0;
        ma_filter.counter = 0;
        ma_filter.output = 0;
    }
}

// 滤波处理逻辑
void process_ma_filter() {
    if (ma_filter.buffer == NULL || ma_filter.current_length == 0) return;

    int target_length = (freq > 1000) ? 100 : 10;
    update_ma_filter_length(target_length);

    ma_filter.sum = ma_filter.sum + test_sin - ma_filter.buffer[ma_filter.counter];
    ma_filter.output = ma_filter.sum / ma_filter.current_length;
    ma_filter.buffer[ma_filter.counter] = test_sin;
    ma_filter.counter++;
    if (ma_filter.counter == ma_filter.current_length) {
        ma_filter.counter = 0;
    }
    filter_out_X = ma_filter.output; // 同步到原输出变量
}

此方式更适合复杂系统,便于扩展多个滤波器实例。

内容的提问来源于stack exchange,提问作者Trex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:59:53