资讯中心

联系我们

深圳市维立信电子科技有限公司
地址:深圳市福田区红荔路第一世界广场A座8D-E
咨询电话:0755-83766766
E-mail:info@welissom.com

信号发生器脚本中如何优化代码结构?

2025-10-13 10:49:30  点击:

在信号发生器脚本中优化代码结构,能够显著提升代码的可读性、可维护性和性能。以下是针对信号发生器脚本的代码结构优化方法,涵盖模块化设计、面向对象编程、性能优化和错误处理等方面:


一、模块化设计:拆分功能,降低耦合


1. 按功能划分模块


将信号发生器的核心功能拆分为独立模块,每个模块负责单一职责。例如:


波形生成模块:生成正弦波、方波、锯齿波等基础波形。


调制模块:实现幅度调制(AM)、频率调制(FM)、相位调制(PM)。


滤波模块:对信号进行低通、高通、带通滤波。


输出控制模块:管理DAC/ADC通信、硬件接口配置。


参数配置模块:读取用户输入或配置文件,设置频率、幅度等参数。


示例目录结构:


signal_generator/├── core/               # 核心算法│   ├── waveform.py     # 波形生成│   ├── modulation.py   # 调制算法│   └── filter.py       # 滤波算法├── hardware/           # 硬件接口│   ├── dac_driver.py   # DAC控制│   └── adc_reader.py   # ADC读取├── config/             # 配置管理│   └── settings.py     # 参数配置└── main.py             # 主程序入口


2. 定义清晰的接口


每个模块通过函数或类暴露接口,隐藏内部实现细节。


示例:waveform.py 定义生成正弦波的接口:


pythondef generate_sine(freq: float, sample_rate: float, duration: float) -> np.ndarray:"""生成正弦波样本    Args:        freq: 频率(Hz)        sample_rate: 采样率(Hz)        duration: 持续时间(秒)    Returns:        NumPy数组,包含波形样本    """t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)return np.sin(2 * np.pi * freq * t)


二、面向对象编程(OOP):封装与复用


1. 使用类封装信号发生器


将信号发生器的状态和行为封装为类,便于管理和扩展。例如:


python


class SignalGenerator:


def __init__(self, sample_rate: float):


self.sample_rate = sample_rate


self.freq = 1e3  # 默认频率


self.amp = 1.0   # 默认幅度


self.wave_type = "sine"  # 默认波形类型


def set_parameters(self, freq: float, amp: float, wave_type: str):


"""设置信号参数"""


self.freq = freq


self.amp = amp


self.wave_type = wave_type


def generate(self, duration: float) -> np.ndarray:


"""生成信号样本"""


t = np.linspace(0, duration, int(self.sample_rate * duration), endpoint=False)


if self.wave_type == "sine":


return self.amp * np.sin(2 * np.pi * self.freq * t)


elif self.wave_type == "square":


return self.amp * np.sign(np.sin(2 * np.pi * self.freq * t))


# 其他波形类型...


2. 继承与多态:扩展信号类型


通过继承实现不同信号类型的扩展,避免重复代码。例如:


python


class BaseWaveform:


def generate(self, t: np.ndarray) -> np.ndarray:


raise NotImplementedError


class SineWave(BaseWaveform):


def __init__(self, freq: float, amp: float):


self.freq = freq


self.amp = amp


def generate(self, t: np.ndarray) -> np.ndarray:


return self.amp * np.sin(2 * np.pi * self.freq * t)


class SquareWave(BaseWaveform):


def generate(self, t: np.ndarray) -> np.ndarray:


return self.amp * np.sign(np.sin(2 * np.pi * self.freq * t))


三、性能优化:提升运行效率


1. 向量化计算


使用NumPy等库进行向量化操作,替代Python循环,显著提升计算速度。


示例:生成正弦波时,避免逐点计算:


python


# 低效:Python循环


def generate_sine_slow(freq, sample_rate, duration):


samples = []


for i in range(int(sample_rate * duration)):


t = i / sample_rate


samples.append(np.sin(2 * np.pi * freq * t))


return np.array(samples)


# 高效:NumPy向量化


def generate_sine_fast(freq, sample_rate, duration):


t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)


return np.sin(2 * np.pi * freq * t)


2. 缓存重复计算结果


对频繁调用的计算结果(如滤波器系数)进行缓存,避免重复计算。


示例:使用functools.lru_cache缓存滤波器设计:


python


from functools import lru_cache


@lru_cache(maxsize=32)


def design_lowpass_filter(cutoff: float, sample_rate: float, order: int):


"""设计低通滤波器并缓存结果"""


# 使用SciPy设计滤波器...


return b, a


3. 并行化处理


对独立任务(如多通道信号生成)使用多线程或多进程并行处理。


示例:使用concurrent.futures生成多通道信号:


python


from concurrent.futures import ThreadPoolExecutor


def generate_channel(freq: float, sample_rate: float, duration: float):


t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)


return np.sin(2 * np.pi * freq * t)


def generate_multichannel(freqs: list, sample_rate: float, duration: float):


with ThreadPoolExecutor() as executor:


channels = list(executor.map(


lambda f: generate_channel(f, sample_rate, duration),


freqs


))


return np.stack(channels, axis=1)  # 合并为多通道信号


四、错误处理与健壮性


1. 参数验证


在关键函数入口处验证参数合法性,避免无效输入导致崩溃。


示例:


pythondef generate_sine(freq: float, sample_rate: float, duration: float) -> np.ndarray:if freq <= 0:raise ValueError("Frequency must be positive")if sample_rate <= 2 * freq:raise ValueError("Sample rate must be > 2 * frequency (Nyquist criterion)")# 生成波形...


2. 异常捕获与日志记录


捕获硬件操作等可能失败的异常,并记录详细日志。


示例:


python


import logging


logging.basicConfig(level=logging.INFO)


logger = logging.getLogger(__name__)


def write_to_dac(samples: np.ndarray, device_path: str):


try:


with open(device_path, "wb") as f:


f.write(samples.tobytes())


except IOError as e:


logger.error(f"Failed to write to DAC: {e}")


raise


五、配置管理:灵活性与可扩展性


1. 使用配置文件


将参数(如频率范围、采样率)存储在配置文件(如YAML、JSON)中,便于修改。


示例:config/settings.yaml:


yamlsignal_generator:sample_rate: 10e6  # 10MHzdefault_freq: 1e3  # 1kHzwave_types: ["sine", "square", "sawtooth"]


2. 命令行参数解析


使用argparse或click库解析命令行参数,覆盖默认配置。


示例:


python


import argparse


def parse_args():


parser = argparse.ArgumentParser()


parser.add_argument("--freq", type=float, default=1e3, help="Signal frequency (Hz)")


parser.add_argument("--wave", choices=["sine", "square"], default="sine", help="Waveform type")


return parser.parse_args()


六、代码复用与第三方库


1. 复用现有库


优先使用成熟的第三方库(如NumPy、SciPy、PyAudio)实现核心功能,避免重复造轮子。


示例:使用scipy.signal设计滤波器:


python


from scipy.signal import butter, lfilter


def apply_lowpass_filter(data: np.ndarray, cutoff: float, sample_rate: float, order: int):


b, a = butter(order, cutoff / (0.5 * sample_rate), btype="low")


return lfilter(b, a, data)


2. 插件化架构


通过插件机制支持扩展信号类型或调制方式,无需修改主程序。


示例:定义插件接口:


python


class WaveformPlugin:


def generate(self, t: np.ndarray) -> np.ndarray:


raise NotImplementedError


# 插件实现(如三角波)


class TriangleWave(WaveformPlugin):


def generate(self, t: np.ndarray) -> np.ndarray:


return 2 * np.abs(2 * (t % 1) - 1) - 1  # 归一化到[-1, 1]


七、文档与测试:保障质量


1. 代码注释与文档字符串


为模块、类和函数添加清晰的文档字符串(Docstring),说明用途、参数和返回值。


示例:


pythondef generate_square(freq: float, sample_rate: float, duration: float) -> np.ndarray:"""生成方波信号    Args:        freq: 频率(Hz)        sample_rate: 采样率(Hz)        duration: 持续时间(秒)    Returns:        NumPy数组,包含方波样本(取值:-1或1)    """t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)return np.sign(np.sin(2 * np.pi * freq * t))


2. 单元测试与集成测试


编写测试用例验证模块功能,使用pytest或unittest框架。


示例测试:


python


import pytest


import numpy as np


def test_generate_sine():


freq = 1e3


sample_rate = 10e3


duration = 0.01


wave = generate_sine(freq, sample_rate, duration)


assert len(wave) == int(sample_rate * duration)


# 验证频率是否正确(通过FFT分析主频)


fft_result = np.fft.fft(wave)


dominant_freq = np.argmax(np.abs(fft_result[:len(fft_result)//2])) * sample_rate / len(wave)


assert np.isclose(dominant_freq, freq, atol=1)  # 允许1Hz误差


总结


优化信号发生器脚本的代码结构需遵循以下原则:


模块化:拆分功能为独立模块,降低耦合。


面向对象:使用类封装状态和行为,支持扩展。


性能优化:向量化计算、缓存结果、并行处理。


健壮性:参数验证、异常捕获、日志记录。


灵活性:配置管理、命令行参数、插件化架构。


可维护性:文档注释、单元测试、代码复用。


通过以上方法,可显著提升信号发生器脚本的质量、性能和可维护性,适应复杂应用场景的需求。