filter_dc_notch16

本文介绍了一种去除信号直流分量的算法实现,通过一个特定的函数filter_dc_notch16来处理输入信号,利用反馈机制实现直流分量的有效过滤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看不懂这个函数,如何去除直流分量?


static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride)
{
   int i;
   spx_word16_t den2;
#ifdef FIXED_POINT
   den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius));
#else
   den2 = radius*radius + .7*(1-radius)*(1-radius);
#endif   
   /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/
   for (i=0;i<len;i++)
   {
      spx_word16_t vin = in[i*stride];
      spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15);
#ifdef FIXED_POINT
      mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1);
#else
      mem[0] = mem[1] + 2*(-vin + radius*vout);
#endif
      mem[1] = SHL32(EXTEND32(vin),15) - MULT16_32_Q15(den2,vout);
      out[i] = SATURATE32(PSHR32(MULT16_32_Q15(radius,vout),15),32767);                                                                                                                                      
   }
}


fmcw测距 matlab%% FMCW雷达信号干扰消除与距离测量 clear; close all; clc; %% 参数设置 c = 3e8; % 光速 (m/s) fc = 24e9; % 中心频率 (Hz) B = 100e6; % 带宽 (Hz) T = 5e-6; % 扫频周期 (s) max_range = 150; % 最大作用距离 (m) num_signals = 5; % 每文件信号段数量 L = 100; % FFT零填充倍数 files = {'fmcw_range_20210530_013230.mat', 'fmcw_range_20210530_013250.mat'}; % 计算理论频率分辨率 range_res = c / (2 * B); % 理论距离分辨率 fprintf('理论距离分辨率: %.2f m\n', range_res); % 创建结果目录 if ~exist('results', 'dir') mkdir('results'); end %% 主处理循环 for file_idx = 1:length(files) filename = files{file_idx}; fprintf('\n处理文件: %s\n', filename); % 加载数据 data = load(filename); % 检查数据结构 if isfield(data, 'data') radar_data = data.data; else error('文件 %s 中未找到 "data" 结构', filename); end distances = zeros(1, num_signals); % 存储各段距离测量值 all_results = cell(1, num_signals); % 创建文件专属结果目录 [~, name] = fileparts(filename); result_dir = fullfile('results', name); if ~exist(result_dir, 'dir') mkdir(result_dir); end for k = 1:num_signals % 获取当前信号段 if isfield(radar_data{k}, 'I') && isfield(radar_data{k}, 'Q') I_orig = radar_data{k}.I; Q_orig = radar_data{k}.Q; else error('信号段 %d 缺少 I 或 Q 数据', k); end N = length(I_orig); % 信号长度 fs = N / T; % 采样率 (Hz) t = (0:N-1)/fs * 1e6; % 时间向量 (微秒) % ===== 1. 原始信号分析 ===== s_orig = I_orig + 1j*Q_orig; % 原始复信号 % 时域绘图 fig1 = figure('Name', sprintf('信号 %d - 原始时域', k), 'Position', [100, 100, 1200, 800]); subplot(2,1,1); plot(t, I_orig, 'b', 'LineWidth', 1.5); title(sprintf('原始信号 - 段 %d - I 通道', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; subplot(2,1,2); plot(t, Q_orig, 'r', 'LineWidth', 1.5); title(sprintf('原始信号 - 段 %d - Q 通道', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; % 保存图像 saveas(fig1, fullfile(result_dir, sprintf('signal_%d_original_time.png', k))); % 频域分析 (FFT) f = (-N/2:N/2-1)*(fs/N)/1e6; % 频率轴 (MHz) S_orig = fftshift(fft(s_orig, N)); fig2 = figure('Name', sprintf('信号 %d - 原始频域', k), 'Position', [100, 100, 1200, 600]); plot(f, abs(S_orig), 'LineWidth', 1.5); title(sprintf('原始频谱 - 段 %d', k)); xlabel('频率 (MHz)'); ylabel('幅度'); xlim([-fs/2/1e6, fs/2/1e6]); grid on; % 保存图像 saveas(fig2, fullfile(result_dir, sprintf('signal_%d_original_freq.png', k))); % ===== 2. 干扰分析 ===== % 检查直流偏移 DC_I = mean(I_orig); DC_Q = mean(Q_orig); fprintf('文件 %s - 段 %d: DC偏移 - I: %.4f, Q: %.4f\n', filename, k, DC_I, DC_Q); % 检查频谱异常峰值 [max_val, max_idx] = max(abs(S_orig)); fprintf('文件 %s - 段 %d: 主导频率: %.2f MHz\n', filename, k, f(max_idx)); % 频谱统计 power_total = sum(abs(S_orig).^2); power_dc = abs(S_orig(floor(N/2)+1))^2; % DC分量 power_ratio_dc = power_dc / power_total * 100; % 检查其他干扰峰值 threshold = 0.1 * max_val; % 峰值检测阈值 peak_mask = abs(S_orig) > threshold; peak_mask(floor(N/2)-10:floor(N/2)+10) = 0; % 排除DC附近 num_peaks = sum(peak_mask); fprintf('文件 %s - 段 %d: DC功率占比: %.2f%%, 检测到 %d 个干扰峰值\n', ... filename, k, power_ratio_dc, num_peaks); % ===== 3. 干扰消除 ===== % 消除直流偏移 I_clean = I_orig - DC_I; Q_clean = Q_orig - DC_Q; s_clean = I_clean + 1j*Q_clean; % 如果检测到其他干扰峰值,应用带阻滤波器 if num_peaks > 0 % 识别主要干扰频率 [pks, locs] = findpeaks(abs(S_orig), 'MinPeakHeight', threshold); [~, idx] = sort(pks, 'descend'); num_to_filter = min(3, length(locs)); % 最多过滤3个最强干扰 for p = 1:num_to_filter freq_idx = locs(idx(p)); freq_hz = f(freq_idx) * 1e6; % 转换为Hz % 设计带阻滤波器 bw = 0.1e6; % 带宽100kHz f0 = freq_hz; notch_filter = designfilt('bandstopiir', ... 'FilterOrder', 4, ... 'HalfPowerFrequency1', f0 - bw/2, ... 'HalfPowerFrequency2', f0 + bw/2, ... 'SampleRate', fs); % 应用滤波器 I_clean = filtfilt(notch_filter, I_clean); Q_clean = filtfilt(notch_filter, Q_clean); end s_clean = I_clean + 1j*Q_clean; fprintf('文件 %s - 段 %d: 已应用带阻滤波器消除 %d 个干扰频率\n', filename, k, num_to_filter); end % ===== 4. 处理前后对比 ===== % 时域对比 fig3 = figure('Name', sprintf('信号 %d - 时域对比', k), 'Position', [100, 100, 1200, 800]); subplot(2,2,1); plot(t, I_orig, 'b', 'LineWidth', 1.5); title(sprintf('原始信号 - I 通道 (段 %d)', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; subplot(2,2,2); plot(t, I_clean, 'b', 'LineWidth', 1.5); title(sprintf('处理后信号 - I 通道 (段 %d)', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; subplot(2,2,3); plot(t, Q_orig, 'r', 'LineWidth', 1.5); title(sprintf('原始信号 - Q 通道 (段 %d)', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; subplot(2,2,4); plot(t, Q_clean, 'r', 'LineWidth', 1.5); title(sprintf('处理后信号 - Q 通道 (段 %d)', k)); xlabel('时间 (\mus)'); ylabel('幅度'); grid on; % 保存图像 saveas(fig3, fullfile(result_dir, sprintf('signal_%d_time_comparison.png', k))); % 频域对比 S_clean = fftshift(fft(s_clean, N)); fig4 = figure('Name', sprintf('信号 %d - 频域对比', k), 'Position', [100, 100, 1200, 600]); subplot(1,2,1); plot(f, abs(S_orig), 'b', 'LineWidth', 1.5); title(sprintf('原始频谱 (段 %d)', k)); xlabel('频率 (MHz)'); ylabel('幅度'); xlim([-fs/2/1e6, fs/2/1e6]); grid on; subplot(1,2,2); plot(f, abs(S_clean), 'r', 'LineWidth', 1.5); title(sprintf('处理后频谱 (段 %d)', k)); xlabel('频率 (MHz)'); ylabel('幅度'); xlim([-fs/2/1e6, fs/2/1e6]); grid on; % 保存图像 saveas(fig4, fullfile(result_dir, sprintf('signal_%d_freq_comparison.png', k))); % ===== 5. 高精度频率估计 ===== % 零填充FFT N_zp = N * L; % 零填充后点数 s_clean_zp = [s_clean, zeros(1, N_zp - N)]; S_zp = fft(s_clean_zp, N_zp); f_zp = (0:N_zp-1)*(fs/N_zp); % 只考虑正频率部分 S_zp_pos = S_zp(1:floor(N_zp/2)); f_zp_pos = f_zp(1:floor(N_zp/2)); % 寻找主峰 (排除直流附近) search_min = 0.1e6; % 100kHz search_max = 40e6; % 40MHz search_range = find(f_zp_pos > search_min & f_zp_pos < search_max); if isempty(search_range) error('在有效频率范围内未找到峰值'); end [~, idx] = max(abs(S_zp_pos(search_range))); peak_idx = search_range(1) + idx - 1; f_est = f_zp_pos(peak_idx); % 频率估计精度验证 peak_val = abs(S_zp_pos(peak_idx)); second_peak = max(abs(S_zp_pos(search_range(1:idx-1)))); if isempty(second_peak) second_peak = max(abs(S_zp_pos(search_range(idx+1:end)))); end snr = 20*log10(peak_val / second_peak); fprintf('文件 %s - 段 %d: 估计频率: %.2f MHz, 信噪比: %.2f dB\n', ... filename, k, f_est/1e6, snr); % ===== 6. 距离计算 ===== R = (f_est * c * T) / (2 * B); distances(k) = R; % 保存结果 all_results{k} = struct(... 'I_orig', I_orig, ... 'Q_orig', Q_orig, ... 'I_clean', I_clean, ... 'Q_clean', Q_clean, ... 'S_orig', S_orig, ... 'S_clean', S_clean, ... 'f_est', f_est, ... 'distance', R, ... 'DC_offset', [DC_I, DC_Q], ... 'num_peaks', num_peaks); end % 结果汇总 avg_distance = mean(distances); std_distance = std(distances); fprintf('\n===== 文件 %s 距离测量结果 =====\n', filename); for k = 1:num_signals fprintf('段 %d: %.4f m\n', k, distances(k)); end fprintf('平均距离: %.4f m\n', avg_distance); fprintf('标准差: %.6f m\n', std_distance); % 保存所有结果 save(fullfile(result_dir, 'processed_results.mat'), 'all_results', 'distances', 'avg_distance', 'std_distance'); % 绘制所有段距离测量结果 fig5 = figure('Name', sprintf('文件 %s 距离测量结果', filename), 'Position', [100, 100, 800, 600]); bar(1:num_signals, distances); hold on; yline(avg_distance, 'r--', 'LineWidth', 2); title(sprintf('文件 %s 距离测量结果', filename)); xlabel('信号段'); ylabel('距离 (m)'); legend('各段测量值', sprintf('平均值: %.4f m', avg_distance)); grid on; % 保存图像 saveas(fig5, fullfile(result_dir, 'distance_results.png')); end fprintf('\n处理完成!所有结果保存在 results 目录\n');
最新发布
06-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值