调频(FM)和调幅(AM)信号生成

文章目录

    • 调频(FM)和调幅(AM)信号生成
      • 1. 调频(FM)和调幅(AM)信号原理与信号生成
        • 调幅(AM)原理
        • 调频(FM)原理
      • 2. 可配置参数
      • 3. C语言实现
      • 4. Python验证代码
      • 5. 验证结果说明

不依赖任何第三方库,用C语言生成FM以及AM信号,并使用python进行数据频谱分析,确认C语言实现的正确性。
话不多说,实战开始。

1. 调频(FM)和调幅(AM)信号原理与信号生成

调幅(AM)原理

调幅通过改变载波的振幅来携带信息:

  • 数学表达式:s(t)=Ac[1+μ⋅m(t)]⋅cos⁡(2πfct)s(t) = A_c[1 + \mu \cdot m(t)] \cdot \cos(2\pi f_c t)s(t)=Ac[1+μm(t)]cos(2πfct)
  • AcA_cAc:载波振幅
  • fcf_cfc:载波频率
  • m(t)m(t)m(t):归一化的调制信号(−1≤m(t)≤1-1 \leq m(t) \leq 11m(t)1
  • μ\muμ:调制指数(0~1),控制调制深度
调频(FM)原理

调频通过改变载波的瞬时频率来携带信息:

  • 数学表达式:s(t)=Accos⁡(2πfct+2πkf∫0tm(τ)dτ)s(t) = A_c \cos\left(2\pi f_c t + 2\pi k_f \int_0^t m(\tau)d\tau\right)s(t)=Accos(2πfct+2πkf0tm(τ)dτ)
  • kfk_fkf:频率偏移灵敏度(Hz/Volt)
  • 最大频偏:Δf=kf⋅max⁡(∣m(t)∣)\Delta f = k_f \cdot \max(|m(t)|)Δf=kfmax(m(t))
  • 调制指数:β=Δf/fm\beta = \Delta f / f_mβ=Δf/fmfmf_mfm为调制信号频率)

2. 可配置参数

参数类型AM参数FM参数
载波参数振幅 AcA_cAc振幅 AcA_cAc
频率 fcf_cfc频率 fcf_cfc
调制参数调制频率 fmf_mfm调制频率 fmf_mfm
调制指数 μ\muμ最大频偏 Δf\Delta fΔf
采样参数采样率 fsf_sfs采样率 fsf_sfs
持续时间 TTT持续时间 TTT

3. C语言实现

#include <stdio.h>
#include <stdlib.h>
#include <math.h>// 通用信号配置
typedef struct {float carrier_amp;    // 载波振幅 (A_c)float carrier_freq;   // 载波频率 (f_c)float mod_freq;       // 调制信号频率 (f_m)float mod_index;      // AM调制指数 (μ) / FM最大频偏 (Δf)float duration;       // 信号时长 (秒)int sample_rate;      // 采样率 (f_s)
} SignalConfig;// 生成AM信号并保存为bin文件
void generate_am(const SignalConfig *cfg, const char *filename) {const int num_samples = cfg->duration * cfg->sample_rate;float *signal = malloc(num_samples * sizeof(float));for (int i = 0; i < num_samples; i++) {float t = (float)i / cfg->sample_rate;float mod_signal = sin(2 * M_PI * cfg->mod_freq * t); // 调制信号float carrier = cos(2 * M_PI * cfg->carrier_freq * t); // 载波signal[i] = cfg->carrier_amp * (1 + cfg->mod_index * mod_signal) * carrier;}FILE *file = fopen(filename, "wb");fwrite(signal, sizeof(float), num_samples, file);fclose(file);free(signal);
}// 生成FM信号并保存为bin文件
void generate_fm(const SignalConfig *cfg, const char *filename) {const int num_samples = cfg->duration * cfg->sample_rate;float *signal = malloc(num_samples * sizeof(float));float phase_integral = 0.0f;float dt = 1.0f / cfg->sample_rate; // 时间步长for (int i = 0; i < num_samples; i++) {float t = (float)i / cfg->sample_rate;float mod_signal = sin(2 * M_PI * cfg->mod_freq * t); // 调制信号phase_integral += mod_signal * dt; // 积分项float phase = 2 * M_PI * cfg->carrier_freq * t + 2 * M_PI * cfg->mod_index * phase_integral;signal[i] = cfg->carrier_amp * cos(phase);}FILE *file = fopen(filename, "wb");fwrite(signal, sizeof(float), num_samples, file);fclose(file);free(signal);
}int main() {// AM示例配置SignalConfig am_cfg = {.carrier_amp = 1.0f,.carrier_freq = 1000.0f,  // 1 kHz.mod_freq = 100.0f,       // 100 Hz.mod_index = 0.8f,        // μ=0.8.duration = 0.1f,         // 100 ms.sample_rate = 48000      // 48 kHz};generate_am(&am_cfg, "am_signal.bin");// FM示例配置SignalConfig fm_cfg = {.carrier_amp = 1.0f,.carrier_freq = 1000.0f,  // 1 kHz.mod_freq = 100.0f,       // 100 Hz.mod_index = 200.0f,      // Δf=200 Hz.duration = 0.1f,          // 100 ms.sample_rate = 48000       // 48 kHz};generate_fm(&fm_cfg, "fm_signal.bin");return 0;
}

4. Python验证代码

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import hilbertdef read_bin_file(filename):return np.fromfile(filename, dtype=np.float32)def plot_signal_analysis(signal, sample_rate, title):# 时域图time = np.arange(len(signal)) / sample_rateplt.figure(figsize=(12, 8))plt.subplot(3, 1, 1)plt.plot(time, signal)plt.title(f'{title} - Time Domain')plt.xlabel('Time (s)')plt.ylabel('Amplitude')plt.grid(True)# 频谱图plt.subplot(3, 1, 2)spectrum = np.abs(np.fft.rfft(signal))freqs = np.fft.rfftfreq(len(signal), 1/sample_rate)plt.plot(freqs, 20 * np.log10(spectrum + 1e-10))  # dB 刻度plt.title('Frequency Spectrum')plt.xlabel('Frequency (Hz)')plt.ylabel('Magnitude (dB)')plt.grid(True)plt.xlim(0, sample_rate/2)# 瞬时特征 (仅FM)if "FM" in title:plt.subplot(3, 1, 3)analytic_signal = hilbert(signal)instantaneous_phase = np.unwrap(np.angle(analytic_signal))instantaneous_freq = (np.diff(instantaneous_phase) / (2 * np.pi) * sample_rate)plt.plot(time[:-1], instantaneous_freq)plt.title('Instantaneous Frequency')plt.xlabel('Time (s)')plt.ylabel('Frequency (Hz)')plt.grid(True)plt.ylim(0, 2000)  # 根据载波频率调整plt.tight_layout()plt.savefig(f"{title.replace(' ', '_')}.png")plt.show()# 分析AM信号
am_signal = read_bin_file("am_signal.bin")
plot_signal_analysis(am_signal, 48000, "AM Signal")# 分析FM信号
fm_signal = read_bin_file("fm_signal.bin")
plot_signal_analysis(fm_signal, 48000, "FM Signal")# 验证关键参数
def verify_am(signal, sample_rate, fc, fm, mu):spectrum = np.abs(np.fft.rfft(signal))freqs = np.fft.rfftfreq(len(signal), 1/sample_rate)carrier_idx = np.argmin(np.abs(freqs - fc))sideband_idx = np.argmin(np.abs(freqs - (fc + fm)))measured_mu = 2 * spectrum[sideband_idx] / spectrum[carrier_idx]print(f"AM验证: 设定μ={mu:.2f}, 实测μ={measured_mu:.2f}")def verify_fm(signal, sample_rate, fc, delta_f):analytic_signal = hilbert(signal)instantaneous_freq = (np.diff(np.unwrap(np.angle(analytic_signal))) * sample_rate) / (2 * np.pi)measured_delta_f = (np.max(instantaneous_freq) - np.min(instantaneous_freq)) / 2print(f"FM验证: 设定Δf={delta_f}Hz, 实测Δf={measured_delta_f:.1f}Hz")verify_am(am_signal, 48000, 1000, 100, 0.8)
verify_fm(fm_signal, 48000, 1000, 200)

5. 验证结果说明

  1. AM信号验证

    • 时域图:显示振幅包络按100Hz正弦变化
    • 频谱图:在1kHz载波两侧出现100Hz间隔的边带
    • 调制深度:通过边带与载波幅度比计算μ\muμ
      AM信号验证图
  2. FM信号验证

    • 时域图:恒定振幅,波形疏密变化
    • 频谱图:能量分散在fc±Δff_c \pm \Delta ffc±Δf范围内
    • 瞬时频率:在fc±Δff_c \pm \Delta ffc±Δf之间波动(示例:1000-1400Hz)
      FM信号验证图
  3. 数值验证

     AM验证: 设定μ=0.80, 实测μ=0.80FM验证: 设定Δf=200Hz, 实测Δf=200.3Hz
    

注:实际运行需安装Python科学计算库:pip install numpy matplotlib scipy


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode 热题 100】21. 合并两个有序链表——(解法一)迭代法

Problem: 21. 合并两个有序链表 题目&#xff1a;将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(M N)空间复杂度&#xff1a;O(1)整体思路 这段代码旨在解决…

力扣 hot100 Day40

23. 合并 K 个升序链表 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 //自己写的垃圾 class Solution { public:ListNode* mergeKLists(vector<ListNode*>& lists) {vector<int…

validate CRI v1 image API for endpoint “unix:///run/containerd/containerd.sock“

1.现象pull image failed: Failed to exec command: sudo -E /bin/bash -c "env PATH$PATH crictl pull 172.23.123.117:8443/kubesphereio/pause:3.9"FATA[0000] validate service connection: validate CRI v1 image API for endpoint "unix:///run/container…

【会员专享数据】2013-2024年我国省市县三级逐月SO₂数值数据(Shp/Excel格式)

之前我们分享过2013-2024年全国范围逐月SO₂栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;!该数据来源于韦晶博士、李占清教授团队发布在国家青藏高原科学数据中心网站上的中国高分辨率高质量近地表空气污染物数据集。很多小伙伴拿到数据后反馈栅格数据不太方便使…

锐捷网络重磅发布RG-UNC CS网络数字化平台:四大核心能力重塑企业网络管理新范式

近期&#xff0c;锐捷重磅发布RG-UNC网络数字化平台CS系列产品&#xff0c;通过全网统一融合管理、组网编排及自动化部署、便捷准入与访问控制、全链业务保障与可视四大核心能力&#xff0c;重新定义企业网络管理标准。置身于数字化转型的进程中&#xff0c;您的网络是否还在面…

使用虚拟机远程登陆ensp模拟器交换机

本文使用软件&#xff1a;VMware&#xff0c;eNSP&#xff0c;mobaxterm要登陆ensp里面的设备&#xff0c;需要使用到cloud下面我们先搭建如下拓扑&#xff1a;首先点击cloud&#xff0c;端口一绑定UDP信息&#xff0c;添加&#xff1b;端口2绑定VMnet8网卡&#xff08;注意网段…

显卡GPU的架构和工作原理

显卡GPU&#xff08;图形处理单元&#xff09;是专为并行计算和图形处理设计的芯片&#xff0c;广泛应用于游戏、科学计算、人工智能和数据中心等领域。以下详细介绍GPU的架构和工作原理&#xff0c;涵盖核心组件、计算流程和关键技术&#xff0c;尽量简洁清晰。 一、GPU架构概…

AndFix、Robust 与 Tinker 热修复框架深度对比

AndFix、Robust 与 Tinker 热修复框架深度对比 在 Android 热修复领域&#xff0c;AndFix、Robust 和 Tinker 是三种主流的解决方案&#xff0c;它们在实现原理、使用场景和限制条件上有显著差异。以下是三者的详细对比分析&#xff1a; 一、核心原理对比特性AndFixRobustTinke…

FlashAttention 快速安装指南(避免长时间编译)

简介&#xff1a;FlashAttention 编译太慢&#xff1f;本篇提供无需编译的预编译 wheel 快速安装方案&#xff0c;适配多版本 Python、PyTorch 和 CUDA&#xff0c;极大节省部署时间&#xff01; &#x1f4a1; 背景介绍 FlashAttention 是由 DAO Labs 提出的一种高性能 atten…

openresty增加tcp端口转发

openresty增加tcp端口转发 1.配置文件nginx.conf 增加stream模块 stream {include /etc/nginx/conf.d/stream/*.conf; }2.在nginx/conf/目录下创建个stream文件夹 新增个10000.conf配置文件server {listen 10000;proxy_pass data_tcp; upstream data_tcp {server 10.10.10.2:10…

动态物体滤除算法

图像层面&#xff1a;2D图像分割反投影到3D点云滤除 基于分割 原理&#xff1a;通过2D语义分割&#xff08;如DeepLab、Mask R-CNN&#xff09;识别动态物体&#xff08;车辆、行人&#xff09;&#xff0c;将分割结果反投影至3D点云中滤除。优化方向&#xff1a; 结合时序一致…

Redisson是如何实现分布式锁的?

Redisson 如何实现分布式锁&#xff1f;&#xff08;核心原理与思考&#xff09; Redisson 是一个功能强大的 Redis 客户端&#xff0c;它提供了许多分布式对象和服务&#xff0c;其中就包括分布式锁。Redisson 的分布式锁是基于 Redis 的 Lua 脚本实现的&#xff0c;这保证了操…

Java 导出word 实现饼状图导出--可编辑数据

&#x1f4ca; 支持图表导出功能&#xff01; 支持将 柱状图、折线图 图表以 Word 文档格式导出&#xff0c;并保留图例、坐标轴、颜色、数据标签等完整信息。 如需使用该功能&#xff0c;请私聊我&#xff0c;备注 “导出柱状图 / 折线图”。 生成的效果图如下&#xff1a;示例…

AI大模型平台

在科技浪潮迅猛推进的当下&#xff0c;AI大模型平台宛如一颗璀璨的新星&#xff0c;强势闯入大众视野&#xff0c;以其独特的魅力和强大的功能&#xff0c;深刻地变革着我们生活与工作的每一处角落。从日常智能助手的贴心陪伴&#xff0c;到专业内容创作的灵感激发&#xff1b;…

C# Console App生成的 dll文件

在使用 dotnet 8.0 创建一个 C# console app后&#xff0c;执行完编译操作&#xff0c;会发现除了生成可执行文件外&#xff0c;还生成一个 dll文件。 $ls ConsoleApp1 ConsoleApp1.dll ConsoleApp1.runtimeconfig.json ConsoleApp1.deps.json ConsoleApp1.pdb $ …

【AI】环境——深度学习cuda+pytorch配置

文章目录关键组件及关系显卡驱动GPU DriverCUDACUDA ToolkitcuDNNPytorch各组件版本选择驱动程序CUDA查看驱动及CUDA的最大支持版本CUDA Toolkit选自定义安装检验无法识别nvcccuDNNcondapip换源conda管理py包conda 换源查看列表、创建、克隆、激活、删除conda包管理包安装原则设…

观众信息设置与统计(视频高级分析与统计功能)

Web播放器&#xff08;POLYV-html5-player&#xff09;支持设置观众信息参数&#xff0c;设置后在播放器上报的观看日志中会附带观众信息&#xff0c;这样用户就可以通过管理后台的统计页面或服务端API来查看特定观众的视频观看情况了。 一、观众信息设置 播放器设置观众信息参…

《数据库》 MySQL库表操作

1. SQL语句基础 1.2 SQL简介 SQL&#xff1a;结构化查询语言(Structured Query Language)&#xff0c;在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。使用SQL语句&#xff0c;程序员和数据库管理员可以完成如下的任务 改变数据库的结构 更改系统的安全设置…

DSP的基础平台搭建

1、CCS6.0的安装安装步骤这里就不说了&#xff0c;只谈论最可能遇到的问题&#xff1a;可以看到为需要关闭防火墙和扫描&#xff1b;在这里将其都关闭&#xff0c;然后可以断掉网络&#xff0c;关闭联想管家&#xff0c;可能还是会出现防火墙提示&#xff0c;但是可以安装&…

下一代防火墙-终端安全防护

实验设备1、 山石网科&#xff08;hillstone&#xff09;系列下一代防火墙&#xff08;实训平台v1.0中hillstone设备&#xff09;2、 三层交换机一台&#xff08;实训平台v1.0中cisco vios l2设备&#xff09;3、 二层交换机一台&#xff08;实训平台v1.0中cisco iol switch设备…