如何修改移动平均滤波器代码以适配可变频率信号?
问题描述
原本使用固定长度(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
相关产品推荐
相关产品推荐

