通过 Hilbert 变换实现单边带调制

news2024/11/30 15:44:50

目录

简介

双边带调制

单边带调制

理想的 Hilbert 变换

频谱移位器

SSB 调制的高效实现

总结


        该例子说明如何使用离散 Hilbert 变换来实现单边带调制。Hilbert 变换可应用于调制器和解调器、语音处理、医学成像、波达方向 (DOA) 测量,以及任何简化设计的复信号(正交)处理。

简介

        单边带调制 (SSB) 是幅值调制 (AM) 的一种高效形式,它使用 AM 所用带宽的一半。这种方法在电话、HAM 无线电和 HF 通信(即基于语音的通信)等应用中最受欢迎。此示例说明如何使用 Hilbert 变换器实现 SSB 调制。

        为了说明 SSB 调制中为何需要使用 Hilbert 变换器,我们最好先快速回顾一下双边带调制。

双边带调制

        AM 的一种简单形式是双边带 (DSB) 调制,它通常由载波频率任一侧的调制信号的两个频移副本组成。更准确地说,这称为一个 DSB 抑制载波,定义为

         其中 m(n) 通常称为消息信号,而 f 0 是载波频率。如上面的方程所示,DSB 调制包括将消息信号 m(n) 乘以载波 cos(2πf0n/fs),因此,我们可以使用傅里叶变换的调制定理来计算 f(n) 的变换

        其中 M(f) 是 m(n) 的离散时间傅里叶变换 (DTFT)。如果消息信号是带宽为 W 的低通信号,则 F(f) 是具有两倍带宽的带通信号。让我们来查看 DSB 信号及其频谱的示例。

% Define and plot a message signal which contains three tones at 500, 600,
% and 700 Hz with varying amplitudes.
Fs = 10e3;
t = 0:1/Fs:0.1-1/Fs;
m = sin(2*pi*500*t) + 0.5*sin(2*pi*600*t) + 2*sin(2*pi*700*t);
plot(t,m)

grid
xlabel('Time')
ylabel('Amplitude')
title('Message Signal m(n)')

        如图所示:

         下面我们计算并绘制消息信号的功率谱。

periodogram(m,[],4096,Fs,'power','centered')
ylim([-75 12])

        如图所示:

         双侧功率谱清楚地显示 DC 附近的三个音调。如果我们进一步放大,就能读出每个分量的功率。

xlim([0.1 1])
ylim([-18 2])

        如图所示:

        500 Hz 音调的功率大约为 –6 dB,600 Hz 音调的功率为 –12 dB,700 Hz 音调的功率为 0 dB,分别对应于消息信号的音调幅值 1、0.5 和 2。使用此消息信号 m(n),让我们将它乘以载波来产生 DSB 信号,并查看其频谱。

fo = 3.5e3; % Carrier frequency in Hz
f = m.*cos(2*pi*fo*t);
idx = 100;
plot(t(1:idx),f(1:idx),t(1:idx),m(1:idx),':')
grid

xlabel('Time')
ylabel('Amplitude')
title('Message Signal and Message Signal Modulated')
legend('Modulated Message Signal','Message Signal m(n)')

        如图所示:

         蓝色实线是调制的消息信号,红色虚线是缓慢变化的消息信号。在这种情况下,我们调制信号的功率谱是

periodogram(f,[],4096,Fs,'power','centered')
ylim([-75 0])

        如图所示:

        我们可以看到,消息信号(三个音调)已移位到中心频率 f0。此外,因为幅值减半,每个分量的功率已降至四分之一,如调制后的 m(n) 的 DTFT 所示。让我们放大以查看新功率值 

ylim([-20 0])

        如图所示:

         我们的正频率分量现在为 –6 dB、–18 dB 和 –12 dB。现在我们已定义 DSB 调制,接下来查看单边带调制。

单边带调制

        单边带 (SSB) 调制类似于DSB调制,但它不使用整个频谱,而是使用滤波器来选择下边带或上边带。下边带或上边带的选择分别产生下边带 (LSB) 或上边带 (USB) 调制。有两种方法可以消除其中一个边带,一种是滤波器方法,另一种是定相方法。由于需要严格的滤波器,对上边带或下边带进行选择性滤波的过程很困难,尤其是当信号内容接近DC时。此示例说明如何使用定相方法,该方法使用Hilbert变换器来实现SSB调制。

        SSB 调制要求将消息信号移位到另一个中心频率,而不像 DSB 调制那样产生成对的频率分量 X(f−f0) 和 X(f+f0),即避免对上边带或下边带进行滤波。这可以通过使用 Hilbert 变换器来实现。

        在讨论理想的 Hilbert 变换在 SSB 调制中的应用之前,让我们先回顾一下其定义和属性。这将有助于理解其在SSB调制中的应用。

理想的 Hilbert 变换

        离散Hilbert变换过程是指将信号的负频率相位提前90度,正频率相位延后90度。对 Hilbert 变换的结果进行移位 (+j) 并将其添加到原始信号会产生下文所示的复信号。

        如果是  的 Hilbert 变换,则:

         是一种称为解析信号的复信号。下图显示通过理想的 Hilbert 变换生成的解析信号。

         解析信号的一个重要特征是其频谱内容位于正奈奎斯特区间中。这是因为如果我们将解析信号(复信号)的虚部移位90度 (+j) 并将其加到实部,则负频率将抵消,而正频率将增加。这会产生没有负频率的信号。此外,复信号中频率分量的幅值是实信号中频率分量的幅值的两倍。这类似于单侧频谱,它包含正频率的总信号功率。

        接下来我们介绍频谱位移器。频谱移位器通过调制基于我们要移动其频谱的信号形成的解析信号来对信号的频谱内容进行移位(平移)。此概念可用于SSB调制,如下文所示。

频谱移位器

        使用上面定义的消息信号m(n),我们将通过 Hilbert 变换创建一个解析信号,然后将其调制到所需的中心频率。方案如下图中所示。

         使用这种频谱移位方法将确保我们信号的功率移至感兴趣的频率,同时最终保持实数值信号。

        如前所述,解析信号由原始实数值信号加上该实信号的Hilbert变换组成。通过Signal Processing Toolbox™中的Hilbert函数运行实信号将产生解析信号。

注意:Hilbert 函数产生完整的解析信号(复信号),而不仅仅是虚部。

mc = hilbert(m);

        我们还可以计算并绘制基于我们的消息信号 m(n) 构造的解析信号的频谱内容。

periodogram(mc,[],4096,Fs,'power','centered')
ylim([-75 6])

        如图所示:

         如频谱图所示,我们的解析信号是复信号,但仅包含正频率分量。此外,如果我们测量功率,或在正频率分量上进一步放大图,我们将看到解析信号的频率分量的功率是实信号的正(或负)频率分量的总功率的两倍,即它类似于包含信号总功率的单侧频谱。请查看以下经过放大的图。

xlim([0.1 1])
ylim([-10 6])

        如图所示:

         我们看到解析信号(复信号)的频率分量 500 Hz、600 Hz 和 700 Hz 的功率分别约为 0、–6 dB 和 6dB,这是原始信号的总功率。这些值对应于我们的原始实数值信号,它有三个音调,幅值分别为 1、0.5 和 2。

        在这里,我们可以调制解析信号,将频谱内容移至另一个中心频率而不产生频率分量对组,并保持实数值信号。

        为了将信号调制到载波频率 f0,我们将解析信号乘以一个指数。 

mcm = mc.*exp(1i*2*pi*fo*t);

        如频谱移位器图中所示,调制信号后,我们将计算实部。其频谱是

periodogram(real(mcm),[],4096,Fs,'power','centered')
ylim([-75 0])

        如图所示:

         如上图所示,我们的信号已调制到新中心频率 f0,但没有创建频率对组,即它产生了上边带。

        如果我们将上面的频谱图与 DSB 调制进行比较,我们可以看到频谱移位器完成了 SSB 调制。

SSB 调制的高效实现

        从前面的推论中,我们可以看出 SSB 调制信号 f(n) 可以写为

        其中是解析信号,定义为

        展开此方程并提取实部,我们得到 

        这会产生一个单一上边带 (SSBU)。同样,我们可以通过以下方式定义 SSB 下边带 (SSBL) 

        上面的 SSBU 方程提出了一种更高效的实现 SSB 的方法。该方法并不执行的复数乘法,然后舍弃虚部;而是通过实现如下所示的 SSBU 只计算所需的量。如下图所示:

        为了实现上面所示的 SSB 调制,我们需要计算消息信号 m(n) 的 Hilbert 变换,并调制两个信号。但在此之前,我们需要指出一个事实,即理想的 Hilbert 变换器是不可实现的。不过,我们可以使用已开发的逼近 Hilbert 变换器的算法,例如 Parks-McClellan FIR 滤波器设计方法。Signal Processing Toolbox™ 提供设计此类滤波器的firpm函数。此外,因为滤波器会引入延迟,我们需要通过将延迟(N/2,其中 N 是滤波器阶数)添加到乘以余弦项的信号中来补偿该延迟,如下所示。

        对于 FIR Hilbert 变换器,我们将使用奇数长度滤波器,它在计算上比偶数长度滤波器更高效。尽管偶数长度滤波器的通带误差较小。奇数长度滤波器能更节省计算资源,是因为这些滤波器具有几个零值系数。此外,使用奇数长度滤波器需要移位一个整数时间延迟,而偶数长度滤波器需要移位一个小数时间延迟。对于奇数长度滤波器,Hilbert 变换器的幅值响应在 w=0 和 w=π 处为零。对于偶数长度滤波器,幅值响应不必在 π 处为 0,因此它们具有更高的带宽。对于奇数长度滤波器,有用带宽限制为

        让我们设计滤波器并绘制其零相位响应。        

Hd = designfilt('hilbertfir','FilterOrder',60, ...
    'TransitionWidth',0.1,'DesignMethod','equiripple');

hfv = fvtool(Hd,'MagnitudeDisplay','Zero-phase', ...
    'FrequencyRange','[-pi, pi)');
hfv.Color = 'white';

         如图所示:

        为了逼近 Hilbert 变换,我们将使用滤波器对消息信号进行滤波。 

m_tilde = filter(Hd,m);

        然后,上边带信号是

G = filtord(Hd)/2;   % Filter delay
m_delayed = [zeros(1,G),m(1:end-G)];
f = m_delayed.*cos(2*pi*fo*t) - m_tilde.*sin(2*pi*fo*t);

        频谱是

periodogram(f,[],4096,Fs,'power','centered')
ylim([-75 0])

        如图所示:

        如上图所示,我们成功将消息信号(三个音调)调制到 3.5 kHz 的载波频率,并且只保留上边带。 

总结

        我们看到,通过使用 Hilbert 变换的逼近,我们可以产生解析信号,这在需要频谱移位的许多信号应用中很有用。具体来说,我们已看到如何使用逼近 Hilbert 变换器来实现单边带调制。        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1165733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“Redis在分布式系统中的应用与优化“

文章目录 引言一、Redis的简介1. Redis的基本概念2. Redis在分布式系统中的优势 二、Windows、CentOS安装RedisCentOS安装RedisWindows安装Redis 三、Redis的常用命令总结 引言 在当今互联网时代,随着数据量的不断增长和用户访问量的激增,分布式系统的应…

将一个Series序列转化为数据框Dataframe格式Series.to_frame()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将一个Series序列 转化为Dataframe格式 Series.to_frame() [太阳]选择题 关于以下代码的说法中正确的是? import pandas as pd s pd.Series([1,2],name"myValue") print("【显…

【QT】如何理解Widget::Widget(QWidget *parent) :QWidget(parent)

‪qwidget.cpp所在路径&#xff1a;D:\Qt\Qt5.9.9\5.9.9\Src\qtbase\src\widgets\kernel\qwidget.cpp 本文重点&#xff1a;如何理解下面这段代码? 一、类的继承和派生 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>class Widget : public QWidget {…

【PID专题】控制算法PID之微分控制(D)的原理和示例代码

微分&#xff08;D&#xff09;项是PID控制器的一个组成部分&#xff0c;它对系统的控制输出做出反应&#xff0c;以减小系统的过度调节和减小响应的快速变化。微分项的作用是在控制系统中引入一个滞后效应&#xff0c;以帮助系统平稳响应。 以下是微分&#xff08;D&#xff0…

PP-OCRv4-server-det模型训练

PP-OCRv4-server-det项目地址https://aistudio.baidu.com/projectdetail/paddlex/6792800 1、数据校验 2、 模型训练 3、评估测试 4、模型部署

OpenCV实战——OpenCV.js介绍

OpenCV实战——OpenCV.js介绍 0. 前言1. OpenCV.js 简介2. 网页编写3. 调用 OpenCV.js 库4. 完整代码相关链接 0. 前言 本节介绍如何使用 JavaScript 通过 OpenCV 开发计算机视觉算法。在 OpenCV.js 之前&#xff0c;如果想要在 Web 上执行一些计算机视觉任务&#xff0c;必须…

Linux之sched_setscheduler调度策略总结(六十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

CMake:探究编译和编译命令

CMake:探究编译和编译命令 导言项目结构相关源码结果 导言 本篇通过展示如何使用来自对应的Check<LANG>SourceCompiles.cmake标准模块的check_<lang>_source_compiles函数&#xff0c;以评估给定编译器是否可以将预定义的代码编译成可执行文件。该命令可帮助确定:…

Idea 对容器中的 Java 程序断点远程调试

第一种&#xff1a;简单粗暴型 直接在java程序中添加log.info()&#xff0c;根据需要打印信息然后打包覆盖&#xff0c;根据日志查看相关信息 第二种&#xff1a;远程调试 在IDEA右上角点击编辑配置设置相关参数在Dockerfile中加入 "-jar", "-agentlib:jdwp…

数据库连接池大小的调整原则

配置连接池是开发人员经常犯的错误。配置池时需要理解几个原则&#xff08;对于某些人来说可能违反直觉&#xff09;。 想象一下&#xff0c;您有一个网站&#xff0c;虽然可能不是 Facebook 规模的&#xff0c;但仍然经常有 10,000 个用户同时发出数据库请求&#xff0c;每秒…

4.RDD编程指南

概述 spark 提供的重要的抽象是一个 弹性分布式数据集(RDD) &#xff0c;能被并行操作的&#xff0c;在集群上分区的集合元素。RDDs 可以通过 hadoop 文件(或共它的 hadoop 支持的文件系统)&#xff0c;或者编程中的 scala 集合&#xff0c;转换它创建 RDD。用户还可以要求 sp…

【Linux】:基础IO

基础IO 一.C语音文件操作1.fopen2.fwrite3.fopen以a方式打开 二.Linux下一切皆文件三.系统调用接口四.文件描述符-fd 共识原理&#xff1a; 1.文件属性内容。 2.文件分为打开文件和未打开文件。 3.打开的文件&#xff1a;进程打开。 4.未打开的文件&#xff1a;在磁盘里存放着。…

在Node.js中,什么是中间件(middleware)?它们的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

企业中台如何进行测试(下篇)

《企业中台如何进行测试》包含了主数据治理测试、统一认证测试、业务集成测试、门户建设测试、数据分析测试等内容。由于篇幅较长&#xff0c;将分为上、下两个篇章与大家分享&#xff0c;在上篇主要从主数据治理和统一认证两个方面对企业中台的测试内容进行介绍&#xff0c;下…

Visual Studio Code 常用快捷键大全

Visual Studio Code 常用快捷键大全 快捷键是编码过程中经常使用&#xff0c;且能够极大提升效率的部分&#xff0c;这里给大家介绍一些VS Code中非常有用的快捷键。 打开和关闭侧边栏 Mac — Command B Windows — Ctrl B Ubuntu — Ctrl B 选择单词 Mac — Command D …

洗衣洗鞋柜洗衣洗鞋小程序

支持&#xff1a;一键投递、上门取衣、自主送店、多种支付方式 TEL: 17638103951(同V) -----------------用户下单-------------- -------------------------多种支付和投递方式------------------------- -----------------商家取鞋--------------

基于冠状病毒群体免疫算法的无人机航迹规划-附代码

基于冠状病毒群体免疫算法的无人机航迹规划 文章目录 基于冠状病毒群体免疫算法的无人机航迹规划1.冠状病毒群体免疫搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用冠状病毒群体…

从关键新闻和最新技术看AI行业发展(2023.10.9-10.22第八期) |【WeThinkIn老实人报】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&…

测试总结模板

​​​​​​​ ​​​​​​​ ​​​​​​​ xx电力工作计划管理系统 系统测试总结 评审核准单 时间 作者 工作内容 版本 确认人 确认时间 2007/11/6 姜全尧 创建延边电力工作计划管理系统测试总结 1.0 …

二叉树OJ题(用前序和中序遍历构建二叉树,用中序和后续遍历构建二叉树)

文章目录 二叉树OJ题一、用前序和中序遍历构建二叉树1.思路2.代码 二、用中序和后续遍历构建二叉树1.思路2.代码 二叉树OJ题 一、用前序和中序遍历构建二叉树 1.思路 1.根据前序遍历找到根结点root 2.在中序遍历中&#xff08;inBegin0和inEndelem.length-1范围之间&#xff09…