文章来源:FPGA开源工作室

1. 预加重滤波器的作用
在语音信号中,声门波激励和口鼻辐射效应共同导致语音信号的高频分量能量要比低频分量弱。预加重(Pre-emphasis)的目的就是:
1 .提升高频分量,平衡语音频谱,使得高频特征更加明显,便于后续的特征提取(如MFCC)。
2.消除发声过程中口唇辐射的影响。
3.在一定程度上抑制工频干扰。
2. 预加重滤波器的使用场景

3. 预加重滤波器的原理与传递函数
预加重通常被建模为一个一阶高通滤波器。它的作用是抑制低频,通过高频。
其数字滤波器的传递函数通常定义为:


4. matlab 实现
function[y, freq_response]= pre_emphasis_analysis(x, fs, alpha, plot_results)
% 完整的预加重分析与实现
% 输入:
% x - 输入语音信号
% fs - 采样频率
% alpha - 预加重系数
% plot_results - 是否绘制结果图表
% 输出:
% y - 预加重后的信号
% freq_response - 滤波器频率响应
if nargin <3
alpha =0.97;
end
if nargin <4
plot_results =true;
end
% 预加重滤波
y = filter([1, -alpha], 1, x);
% 计算频率响应
[h, w]= freqz([1, -alpha], 1, 1024, fs);
freq_response = abs(h);
frequencies = w;
% 绘制结果
if plot_results
plot_preemphasis_results(x, y, frequencies, freq_response, fs, alpha);
end
end
function plot_preemphasis_results(x, y, f, h, fs, alpha)
% 绘制预加重结果
figure('Position', [100, 100, 1200, 800]);
% 时域信号对比
subplot(3, 2, 1);
t =(0:length(x)-1) / fs;
plot(t, x, 'b', 'LineWidth', 1);
title('原始语音信号 (时域)');
xlabel('时间 (s)');
ylabel('幅度');
grid on;
subplot(3, 2, 2);
plot(t, y, 'r', 'LineWidth', 1);
title('预加重后信号 (时域)');
xlabel('时间 (s)');
ylabel('幅度');
grid on;
% 频域对比
N = length(x);
f_axis =(0:N-1) * fs / N;
X = abs(fft(x));
Y = abs(fft(y));
subplot(3, 2, 3);
plot(f_axis(1:N/2), X(1:N/2), 'b', 'LineWidth', 1.5);
title('原始信号频谱');
xlabel('频率 (Hz)');
ylabel('幅度');
grid on;
subplot(3, 2, 4);
plot(f_axis(1:N/2), Y(1:N/2), 'r', 'LineWidth', 1.5);
title('预加重后频谱');
xlabel('频率 (Hz)');
ylabel('幅度');
grid on;
% 滤波器频率响应
subplot(3, 2, 5);
plot(f, 20*log10(h), 'g', 'LineWidth', 2);
title('预加重滤波器频率响应');
xlabel('频率 (Hz)');
ylabel('增益 (dB)');
grid on;
% 频谱对比(重叠)
subplot(3, 2, 6);
plot(f_axis(1:N/2), X(1:N/2)/max(X), 'b--', 'LineWidth', 1, 'DisplayName', '原始');
hold on;
plot(f_axis(1:N/2), Y(1:N/2)/max(Y), 'r-', 'LineWidth', 1.5, 'DisplayName', '预加重');
title('频谱对比 (归一化)');
xlabel('频率 (Hz)');
ylabel('归一化幅度');
legend('show');
grid on;
sgtitle(sprintf('语音预加重分析 (α = %.2f)', alpha));
end

5. 预加重滤波器FPGA实现

module pre_emphasis(
input wire clk,
input wire rst_n,
input wire signed[15:0] data_in,
output reg signed[15:0] data_out
);
// 预加重系数 α = 0.97,Q1.15格式
parameter ALPHA =16'd31782;// 0.97 * 2^15
// 寄存器声明
reg signed[15:0] x_delay;// 延迟寄存器
reg signed[31:0] product_reg;// 乘法结果寄存器
reg signed[15:0] input_reg;// 输入寄存器
// 流水线处理
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
input_reg <=16'sd0;
x_delay <=16'sd0;
product_reg <=32'sd0;
data_out <=16'sd0;
end else begin
// 第一级: 输入和延迟
input_reg <= data_in;
x_delay <= input_reg;// 注意: 这里使用input_reg而不是data_in
// 第二级: 乘法
product_reg <= ALPHA * x_delay;
// 第三级: 减法和输出
data_out <= input_reg - product_reg[30:15];// Q格式调整
end
end
endmodule