[实战]调频Chrip信号生成(完整C语言代码)

调频Chrip信号生成

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

调频Chirp信号原理

调频Chirp信号是一种频率随时间线性变化的信号,其数学表达式为:

s(t) = A * cos(2π * (f₀t + (k/2)t²) + φ)

其中:

  • A:信号幅度
  • f₀:起始频率
  • k:调频率(频率变化速率)
  • φ:初始相位
  • t:时间

瞬时频率为:f(t) = f₀ + k*t

常见可配置参数

  1. 采样率:每秒采样点数 (Hz)
  2. 起始频率:Chirp的初始频率 (Hz)
  3. 结束频率:Chirp的终止频率 (Hz)
  4. 持续时间:信号长度 (秒)
  5. 幅度:信号峰值幅度
  6. 初始相位:信号的初始相位 (弧度)
  7. 方向:频率增加(UP)/减少(DOWN)

C语言实现:生成Chirp信号并保存为BIN文件

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

typedef struct {
    double sample_rate;  // 采样率 (Hz)
    double start_freq;   // 起始频率 (Hz)
    double end_freq;     // 结束频率 (Hz)
    double duration;     // 持续时间 (秒)
    double amplitude;    // 幅度
    double init_phase;   // 初始相位 (弧度)
    int direction;       // 方向: 0=UP, 1=DOWN
} ChirpConfig;

void generate_chirp(ChirpConfig config, const char* filename) {
    // 计算总采样点数
    int total_samples = (int)(config.duration * config.sample_rate);
    float* buffer = (float*)malloc(total_samples * sizeof(float));
    
    // 计算调频率 k (Hz/s)
    double k = (config.end_freq - config.start_freq) / config.duration;
    if (config.direction == 1) {  // DOWN chirp
        k = -k;
        double temp = config.start_freq;
        config.start_freq = config.end_freq;
        config.end_freq = temp;
    }

    // 生成Chirp信号
    for (int i = 0; i < total_samples; i++) {
        double t = i / config.sample_rate;
        double phase = 2 * M_PI * (config.start_freq * t + 0.5 * k * t * t) + config.init_phase;
        buffer[i] = (float)(config.amplitude * cos(phase));
    }

    // 保存为二进制文件
    FILE* file = fopen(filename, "wb");
    fwrite(buffer, sizeof(float), total_samples, file);
    fclose(file);
    free(buffer);
}

int main() {
    // 配置参数示例
    ChirpConfig config = {
        .sample_rate = 48000.0,   // 48 kHz采样率
        .start_freq = 100.0,      // 100 Hz起始
        .end_freq = 10000.0,      // 10 kHz结束
        .duration = 2.0,          // 2秒时长
        .amplitude = 0.8,         // 80%幅度
        .init_phase = 0.0,        // 零相位
        .direction = 0            // UP chirp
    };

    generate_chirp(config, "chirp_signal.bin");
    printf("Chirp信号已生成并保存到 chirp_signal.bin\n");
    return 0;
}

编译运行:

gcc chirp_generator.c -lm -o chirp_generator
./chirp_generator

Python验证:读取BIN文件并分析

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import spectrogram

# 读取二进制文件
def read_chirp_bin(filename):
    with open(filename, 'rb') as f:
        data = np.fromfile(f, dtype=np.float32)
    return data

# 分析Chirp信号
def analyze_chirp(data, sample_rate, config):
    # 创建时间轴
    duration = len(data) / sample_rate
    time = np.linspace(0, duration, len(data))
    
    # 绘制时域波形
    plt.figure(figsize=(12, 8))
    
    plt.subplot(3, 1, 1)
    plt.plot(time, data)
    plt.title('Chirp Signal - Time Domain')
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')
    plt.grid(True)
    plt.xlim(0, min(0.1, duration))  # 显示前100ms细节
    
    # 计算并绘制频谱
    plt.subplot(3, 1, 2)
    fft_result = np.fft.rfft(data)
    freqs = np.fft.rfftfreq(len(data), 1/sample_rate)
    plt.plot(freqs, np.abs(fft_result))
    plt.title('Frequency Spectrum')
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Magnitude')
    plt.grid(True)
    plt.xlim(config['start_freq']-500, config['end_freq']+500)
    
    # 计算并绘制时频谱
    plt.subplot(3, 1, 3)
    f, t, Sxx = spectrogram(data, fs=sample_rate, nperseg=1024)
    plt.pcolormesh(t, f, 10 * np.log10(Sxx), shading='gouraud')
    plt.title('Spectrogram')
    plt.ylabel('Frequency (Hz)')
    plt.xlabel('Time (s)')
    plt.ylim(0, 1.2 * max(config['start_freq'], config['end_freq']))
    plt.colorbar(label='Intensity (dB)')
    
    plt.tight_layout()
    plt.savefig('chirp_analysis.png')
    plt.show()
    
    # 打印关键指标
    expected_k = (config['end_freq'] - config['start_freq']) / config['duration']
    print(f"验证结果:")
    print(f"- 采样点数: {len(data)}")
    print(f"- 持续时间: {duration:.2f}s (预期: {config['duration']}s)")
    print(f"- 频率范围: {freqs[np.argmax(fft_result)]:.0f}Hz (起始预期: {config['start_freq']}Hz)")
    print(f"- 调频斜率: {expected_k:.0f} Hz/s")

# 配置参数(需与C程序一致)
config = {
    'sample_rate': 48000,
    'start_freq': 100,
    'end_freq': 10000,
    'duration': 2.0,
    'amplitude': 0.8,
    'direction': 'UP'
}

# 读取并分析数据
data = read_chirp_bin("chirp_signal.bin")
analyze_chirp(data, config['sample_rate'], config)

验证结果分析

  1. 时域图

    • 显示信号波形随时间变化
    • 初期波形稀疏(低频),后期密集(高频)
  2. 频谱图

    • 显示信号在100Hz-10kHz范围有显著能量
    • 峰值位置与起始频率一致
  3. 时频谱

    • 清晰展示频率随时间线性变化
    • 斜率为 (10000-100)/2 = 4950 Hz/s
    • 验证UP/DOWN方向正确性
      在这里插入图片描述
  4. 控制台输出

    • 报告实际持续时间、频率范围等参数
    • 与输入参数对比验证一致性
        验证结果:
     	- 采样点数: 96000
     	- 持续时间: 2.00s (预期: 2.0s)
     	- 频率范围: 5430Hz (起始预期: 100Hz)
     	- 调频斜率: 4950 Hz/s
    

验证要点

  1. 频率范围:起始/结束频率应与配置一致
  2. 持续时间:信号长度应匹配设定时长
  3. 调频方向:时频谱斜率方向应与配置一致
  4. 线性度:时频谱应呈直线特征
  5. 幅度:时域峰值应与设定幅度匹配

此方案完整实现了Chirp信号的生成、存储和验证流程,所有关键参数均可配置,并通过可视化分析确保信号生成正确性。


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值