使用自功率谱、互功率谱估计滤波器幅频特性

这段时间终于对工程中的随机信号的一般处理方式有点头绪了,功率谱密度估计是十分重要的方式之一,仍需继续深入细化相关内容。


示例:使用自功率谱、互功率谱估计滤波器幅频特性,自己实现 & Matlab自带函数实现。

clc;clear;close all;
fs = 44100;
t = 0:1/fs:1-1/fs;
in = randn(size(t));
 
winlen = 1024;
overlap = winlen/2;
 
% 滤波
order = 1; % 滤波器阶数高后,则曲线不太平滑
fc = 1200;
[b,a] = butter(order, fc/(fs/2), 'low');
out = filter(b, a, in);
 
%% 自己实现cpsd、pwelch。整体思路与上周相同,但将功率谱密度估计方法由 相关法 改为 直接法
segments_i = buffer(in, winlen, overlap, "nodelay"); % 存放输入信号的分段交叠
segments_o = buffer(out, winlen, overlap, "nodelay"); % 存放输出信号的分段交叠
numSegments = size(segments_i, 2);  % 分段数
 
wd = hanning(winlen);
 
spectrum_Pxx = zeros(winlen/2+1,numSegments);  % 存放每段估计的自功率谱密度
spectrum_Pxy = zeros(winlen/2+1,numSegments);  % 存放每段估计的互功率谱密度
 
for i = 1:numSegments  % 分段估计
 
    % 估计输入信号自功率谱密度
    in_fft = fft(segments_i(:,i).*wd);
    N = length(in_fft);
 
    P1 = abs(in_fft/N);
    P2 = P1(1:floor(N/2)+1);
    P2(2:end-1) = 2*P2(2:end-1);
    Pxx_ = P2.^2/(N*fs); 
 
    % 估计输入、输出信号互功率谱密度
    out_fft = fft(segments_o(:,i).*wd);
    P3 = abs(out_fft/N);
    P4 = P3(1:floor(N/2)+1);
    P4(2:end-1) = 2*P4(2:end-1);
    Pxy_ = P4 .* conj(P2) / (N*fs);
 
    % 每段的功率谱密度存起来
    spectrum_Pxx(:,i) = Pxx_;
    spectrum_Pxy(:,i) = Pxy_;
 
end
 
f = fs*(0:N/2)/N;
 
% 计算均值
spectrumAvg_Pxx = mean(spectrum_Pxx, 2);
spectrumAvg_Pxy = mean(spectrum_Pxy, 2);
 
H2 = abs(spectrumAvg_Pxy) ./ abs(spectrumAvg_Pxx);
subplot(311);
plot(f,20*log10(H2));
title("幅频曲线(自己实现的自功率谱、互功率谱估计)");xlabel("频率");ylabel("db");
 
%% 自带pwelch、cpsd
[Pxx,f1] = pwelch(in, hanning(winlen),overlap,winlen,fs);
[Pxy,f2] = cpsd(in, out, hanning(winlen),overlap,winlen,fs);
 
subplot(312);
plot(f1, 20*log10(abs(Pxy ./ Pxx)));
title("幅频曲线(自带的pwelch、cpsd函数)");xlabel("频率");ylabel("db");
 
%% freqz理想幅频特性曲线
[H3, w] = freqz(b,a);
subplot(313);
 
f1 = w*fs/2/pi;
plot(f1,20*log10(abs(H3)));
title("幅频曲线(理想)");xlabel("频率");ylabel("db");

结果图:


遗留问题:

该示例中使用高阶滤波器后,幅频特性曲线仍会有较大的波动,有待在后续学习中解决。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,这是一个信号处理的问题。我会尽力回答你的问题。 首先,我们可以使用butter函数在MATLAB中设计一个带通滤波器。代码如下: ```matlab % 设计带通滤波器 fs = 50e3; % 采样率 fpass = [10e3 20e3]; % 通带频率范围 fstop = [9e3 21e3]; % 阻带频率范围 apass = 1; % 通带最大衰减 astop = 35; % 阻带最小衰减 [n, Wn] = buttord(fpass/(fs/2), fstop/(fs/2), apass, astop); % 计算最小阶数和截止频率 [b, a] = butter(n, Wn); % 求解滤波器系数 % 绘制幅频响应 freqz(b, a, [], fs); ``` 绘制的幅频响应如下图所示: ![带通滤波器幅频响应](https://img-blog.csdnimg.cn/20210923162226199.png) 接下来我们可以生成一个随机的白噪声信号,并使用filter函数将其通过带通滤波器进行滤波。代码如下: ```matlab % 生成白噪声信号 n = 1e5; % 采样点数 x = randn(n, 1); % 将白噪声信号通过带通滤波器滤波 y = filter(b, a, x); % 计算均值、均方值和方差 mean_y = mean(y); rms_y = rms(y); var_y = var(y); ``` 通过带通滤波器滤波后的信号的均值、均方值和方差分别为: ``` mean_y = 0.0002 rms_y = 0.9945 var_y = 0.9890 ``` 接下来我们可以计算白噪声通过带通滤波器后的信号的自相关函数和功率谱密度。代码如下: ```matlab % 计算自相关函数 r = xcorr(y, 'unbiased'); % 绘制自相关函数 figure; plot((-length(r)/2+1:length(r)/2)/fs, r); xlabel('时间 (s)'); ylabel('自相关函数'); % 计算功率谱密度 [Pxx, f] = pwelch(y, [], [], [], fs); % 绘制功率谱密度 figure; plot(f, 10*log10(Pxx)); xlabel('频率 (Hz)'); ylabel('功率谱密度 (dB/Hz)'); ``` 绘制的自相关函数和功率谱密度分别如下图所示: ![带通滤波器通过白噪声信号的自相关函数](https://img-blog.csdnimg.cn/20210923162245886.png) ![带通滤波器通过白噪声信号的功率谱密度](https://img-blog.csdnimg.cn/2021092316225513.png) 最后,我们可以确定并绘制白噪声通过带通滤波器后的信号的一维概率密度函数和频谱。代码如下: ```matlab % 绘制概率密度函数 figure; histogram(y, 100, 'Normalization', 'pdf'); xlabel('幅值'); ylabel('概率密度'); % 计算频谱 Y = fft(y); f = (0:length(Y)-1)'/length(Y)*fs; % 绘制频谱 figure; plot(f, 20*log10(abs(Y))); xlabel('频率 (Hz)'); ylabel('幅值 (dB)'); ``` 绘制的概率密度函数和频谱分别如下图所示: ![带通滤波器通过白噪声信号的概率密度函数](https://img-blog.csdnimg.cn/20210923162312122.png) ![带通滤波器通过白噪声信号的频谱](https://img-blog.csdnimg.cn/20210923162327656.png) 希望这些代码能够帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的马师兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值