【STM32学习笔记】基于频域FFT滤波的音频均衡器方案验证与效果展示
通过上篇文章【STM32学习笔记】简易音乐播放器+FFT频谱显示,以及一些wav文件data数据块、C语言、声学知识总结的方法得到频域信号后,相位保持不变,赋值做一定的修改后做IFFT回时域再发送给DAC芯片播放
·
简介
通过上篇文章【STM32学习笔记】简易音乐播放器+FFT频谱显示,以及一些wav文件data数据块、C语言、声学知识总结
的方法得到频域信号后,相位保持不变,赋值做一定的修改后做IFFT回时域再发送给DAC芯片播放
特点与不足
特点
1、能自由对频域的幅值和频段做处理,处理的精度取决于FFT的点数
2、借助stm32H7的硬件乘法器能保证处理的实时性
不足
1、有比较明显的失真
2、硬件资源消耗很大
分块介绍

1、计算原始相位
for (uint16_t i = 0; i < num_samples; i++)
{
a = complex_input[2 * i];
b = complex_input[2 * i + 1];
phase_output[i] = atan2f(b, a);
}
2、根据原始相位和新的幅值重构频域数据
修改幅值时需要注意,因为频谱的对称性,修改赋值时要同时修改正负半轴
for(uint16_t i = 5; i < 22; i++) new_magnitude[i] = 0.01f;
for(uint16_t i = 1024-5; i > 1024-22; i--) new_magnitude[i] = 0.01f;
/**
* @brief 根据相位和新的幅值重构频域数据
* @param phase : 相位数据
* @param new_magnitude : 新的幅值
* @param complex_output: 复数输出数据
* @param num_samples : 采样点数
* @retval 无
*/
static void reconstruct_complex_data(const float32_t *phase, const float32_t *new_magnitude,
float32_t *complex_output, uint32_t num_samples)
{
for (uint16_t i = 0; i < num_samples; i++)
{
complex_output[2 * i] = new_magnitude[i] * cosf(phase[i]);
complex_output[2 * i + 1] = new_magnitude[i] * sinf(phase[i]);
}
}
3、IFFT得到时域信号
同样输入数据以实部、虚部、实部、虚部的格式存储,该函数处理完后数据依然存储在complex_output中,我们需要的时域数据则只取实部数据即可
arm_cfft_f32(&arm_cfft_sR_f32_len1024, complex_output, 1, 1);
4、异常处理
调试时发现在FFT一组数据的首尾会出现这种现象
下图为matlab用同样方法得到的数据
既然matlab也有相似的现象,那可能是这种方法的数学性质导致的了,因此我仅在信号在头尾约1/3的位置加了个余弦窗
for(uint32_t i = 0; i < blockSize*0.1666f; i++){
w = 0.6f - 0.4f * cosf (PI * i * k);
pbuf[i] *= w;
}
for(uint32_t i = blockSize*0.8333f; i < blockSize; i++){
w = 0.6f - 0.4f * cosf (PI * i * k);
pbuf[i] *= w;
}
资源共享
代码
https://gitee.com/creator-len/study_music
效果展示
[STM32学习]频域滤波EQ方案验证
更多推荐



所有评论(0)