[實戰]調頻(FM)和調幅(AM)信號生成(完整C語言實現)

調頻(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πfc?t)
  • AcA_cAc?:載波振幅
  • fcf_cfc?:載波頻率
  • m(t)m(t)m(t):歸一化的調制信號(?1≤m(t)≤1-1 \leq m(t) \leq 1?1m(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)=Ac?cos(2πfc?t+2πkf?0t?m(τ)dτ)
  • kfk_fkf?:頻率偏移靈敏度(Hz/Volt)
  • 最大頻偏:Δf=kf?max?(∣m(t)∣)\Delta f = k_f \cdot \max(|m(t)|)Δf=kf??max(m(t))
  • 調制指數:β=Δf/fm\beta = \Delta f / f_mβ=Δf/fm?fmf_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設備…