如何从含噪调制波信号中提取有效载荷?代码问题求助
相位调制信号解调代码异常排查
我有一个double类型数组,存储带编码数据的含噪调制无线电信号(对应相位调制信号)。按照老师提供的算法解调:对数组做FFT,计算每个FFT复数结果的相位φ=atan(Q/I)(Q是实部,I是虚部),按比特段求和,和大于阈值L标记为1,否则为0。但运行代码后结果异常:有时0对应的求和值反而大于1,无法正确提取比特序列,噪声功率以分贝为单位,求排查问题。
问题代码
std::vector<double> y_axis = generateWave(); // The noised signal fftw_complex * out = reinterpret_cast<fftw_complex *>(fftw_malloc(sizeof (fftw_complex) * y_axis.size())); fftw_complex * in = reinterpret_cast<fftw_complex *>(fftw_malloc(sizeof (fftw_complex) * y_axis.size())); for (std::size_t i{0}; i < y_axis.size(); i++) { in[i][0] = y_axis[i]; in[i][1] = 0.0; } fftw_plan plan = fftw_plan_dft_1d(y_axis.size(), in, out, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); std::vector<double> result_vector(y_axis.size()); for (std::size_t i{0}; i < result_vector.size(); i++) { result_vector[i] = std::atan(out[i][0] / out[i][1]); } const std::size_t per_bit = result_vector.size() / bit_sequence.size(); for (std::size_t i = 0; i < bit_sequence.size(); i++) { double current_sum = 0.0; for (std::size_t j{0}; j < per_bit; j++) current_sum += result_vector[i * per_bit + j]; std::cerr << bit_sequence[i] << " " << current_sum << std::endl; } fftw_free(in); fftw_free(out);
核心问题排查
相位计算完全错误:
- FFTW的
fftw_complex定义为[0]是实部(I分量),[1]是虚部(Q分量),你搞反了Q和I的位置,正确的atan(Q/I)应该是atan(out[i][1]/out[i][0]) std::atan只能返回[-π/2, π/2]的结果,无法区分四个象限的相位,会导致相位折叠错误,必须用std::atan2(out[i][1], out[i][0]),它能输出[-π, π]的完整相位
- FFTW的
FFT处理逻辑不符合相位解调原理:
相位调制的信息集中在载波频率对应的FFT bin,你对整个信号FFT后遍历所有点计算相位再分段求和,完全偏离了正确逻辑。正确流程应该是:时域上按比特长度分段,对每一段时域信号做FFT,提取载波频率点的相位,再根据相位差/绝对值判断比特值,而非对全FFT结果分段求和数值稳定性问题:
当噪声导致FFT实部out[i][0]接近0时,out[i][0]/out[i][1]会出现除以0的数值异常,std::atan2可以避免这个问题,因为它的参数是分开传入的比特分段逻辑漏洞:
per_bit = result_vector.size() / bit_sequence.size()仅在总长度是比特数整数倍时有效,否则会丢失末尾数据;同时,你是对FFT后的频域数据分段,这完全错误——相位调制的比特信息是时域上每一段的载波相位,应该在时域分段后再做FFT处理
内容的提问来源于stack exchange,提问作者KonstantIMP
相关产品推荐
相关产品推荐

