返回作品列表

网友作品 #000130 · 提交于 2026/08/11

音色分析工具:示波器CSV声音特征分析对比

★★★★★业余水平AI 编程工具国内其他模型python

作品作者

frey业余水平
开发工具
AI 编程工具
AI 模型
国内其他模型
使用 Skill
python
提交你的作品

作品简介

这是一款分析声音音色的桌面工具:导入示波器导出的「时间、电压」两列 CSV(如 SDS2202X Plus 等型号),程序自动完成基频估计、音名换算、谐波与频谱特征计算,并以文字结论、特征指标表、可视化图表三种形式呈现结果,还支持多个文件叠加对比音色差异。已用 PyInstaller 打包成单文件 exe,双击即可运行,无需安装任何环境。

界面左侧为已加载文件列表,右侧提供概览、波形、频谱、谐波、语谱图、对比六个标签页,随时切换查看;点「导出报告」可把当前文件的分析结论、数据表和图片一次性写出。

核心亮点

  • 一站式分析:自动解析示波器 CSV(识别采样间隔、通道等元数据,多层容错降级),输出 20 余项音色特征
  • 音高识别:用谐波积谱法估计基频,按十二平均律换算音名、八度与音分偏差
  • 指标齐全:频谱质心、带宽、85% 滚降、平坦度、过零率、THD、谐波能量占比等 15 项特征指标表,附逐次谐波数据表
  • 五类图表:波形(整体+细节)、频谱、谐波柱状图、语谱图、多文件归一化频谱对比,支持缩放平移
  • 中文文字结论:自动生成亮度、纯净度、谐波丰富度的人类可读描述,可直接引用进报告
  • 多文件对比:一次加载多个 CSV 后台分析,对比页汇总各文件的基频、音名、质心、THD、平坦度差异
  • 一键导出报告:文字结论 TXT、特征表与谐波表 CSV、图表 PNG 一次写出
  • 免安装运行:打包为单文件 exe 双击即用,CSV 导出采用 UTF-8-BOM,Excel 打开不乱码

技术与工具

  • 技术栈:Python 3.12 + tkinter 界面,numpy/scipy 做信号处理,matplotlib 绘图,uv 管理依赖
  • 架构分层:分析核心、绘图、界面三个模块解耦,核心模块不依赖 GUI、可单独测试复用;文件解析在后台线程执行,界面不卡顿
  • 质量保障:pytest 单元测试用合成信号校验基频精度与谐波检测,ruff/mypy 做静态检查
  • 日志系统:按日期分文件、单文件超 5MB 自动轮转、启动时清理 30 天前的旧日志
  • 开发方式:作者为业余水平,借助 AI 编程类工具与国内免费大模型完成

开发过程

  • 项目按「核心计算—可视化—界面」分层搭建,约 1300 行源码、6 个 Python 文件
  • 先用 440Hz、200Hz 加谐波等合成信号做单元测试验证算法精度,再用 PyInstaller 打包成约 95MB 的单文件 exe 交付

适用场景

  • 乐器与发声装置的音色测评:对比不同样品的基频、亮度、谐波结构,辅助调音与选材
  • 声学课程实验与科研:把示波器采集的声音数据快速变成量化指标和报告图表
原始提交内容(点开查看,可复制全文去问 AI)

timbre-analyzer — 声音音色分析工具

项目定位

一个基于 Python + tkinter + matplotlib 的桌面 GUI 程序,用于分析示波器导出的声音电压 CSV 数据,自动提取音色特征并以文字结论、特征表格、可视化图表三种形式展示,并附带多文件频谱对比功能。已完成打包,双击 .exe 即可运行,无需安装任何环境。


目录结构

timbre_analyzer/
 src/timbre_analyzer/           源代码(6 个 .py 文件,~1300 行)
    __init__.py                包入口
    main.py                    程序入口(配置日志  启动 GUI)
    logging_setup.py           日志系统(按日期分文件、自动轮转、过期清理)
    core.py                    音色分析核心(423 行,无 GUI 依赖)
    plotting.py                可视化绘制(232 行,5 张图)
    ui/
        app.py                 tkinter GUI 界面(401 行)

 tests/
    test_core.py               pytest 单元测试(3 项,合成信号验证)

 scripts/
    build_exe.py               PyInstaller 打包脚本(产出一个 .exe)

 dist/
    音色分析工具.exe            打包成品(~95MB,双击运行)

 assets/                        资源目录(图标等)
 logs/                          运行时日志
 pyproject.toml                 项目元数据、依赖、脚本入口、lint 配置
 uv.lock                        锁定依赖版本
 音色分析工具.spec              PyInstaller 规范文件(自动生成)

模块职责

1. core.py — 分析核心(423 行)

不依赖任何 GUI / matplotlib,可脱离界面单独测试或复用。内含 6 个公开函数、5 个 dataclass 数据结构:

类/函数 职责
SignalData 信号数据对象(时间轴、电压、采样率、来源通道、文件名)
HarmonicRow 单个谐波信息(次数、频率、幅值、相对 dB/百分比)
TimbreFeatures 音色特征汇总(20+ 项指标)
AnalysisResult 完整分析结果(信号 + 特征 + 谐波表 + 频谱数据)
load_oscilloscope_csv() 解析 SDS2202X Plus 等示波器的 CSV(自动识别元数据 + 数据分界,退化为全文件扫描)
analyze_timbre() 一站式分析入口:基频 音名 谐波 频谱特征 时域特征 文字描述
build_summary_text() 生成人类可读的中文分析结论
build_feature_table() 生成 15 项特征指标表(指标名/数值/说明)
build_harmonic_table() 生成谐波数据表(次数/频率/相对幅值/相对 dB)
build_comparison_table() 生成多文件对比表(文件名/基频/音名/质心/THD/平坦度/丰富度)

分析算法

步骤 方法 细节
CSV 解析 正向扫描 + 退化为数值行检测 先识别元数据(Sample Interval / Source / Second 表头),找不到表头则退化扫描首行含两个浮点数的位置
基频 F0 谐波积谱 HPS(Harmonic Product Spectrum) 对幅度谱做 2/3/4/5 倍降采样后相乘,突出真正的基频;再用抛物线插值细化峰值位置
音名换算 十二平均律公式 MIDI = 69 + 12·log₂(f/440),反算音名 + 八度 + 音分偏差
谐波提取 局部峰值搜索 在 f0×n ± 3% 范围内取最大值,容忍轻微失谐;约束至奈奎斯特频率,最多 12 次谐波
THD (Σ谐波功率) / 基频幅值 涵盖 2–12 次谐波
频谱质心 Σ(freqs × mag) / Σ(mag) 亮度指标,越高越明亮
频谱带宽 (Σ((f-centroid)² × mag) / Σ(mag)) 频带集中程度
频谱滚降 85% 累积能量 searchsorted 85% 能量所在的频率上限
频谱平坦度 geometric_mean(power²) / arithmetic_mean(power²) 0纯乐音,1白噪声
过零率 `Σ( Δsign
文字描述 三级阈值决策 质心亮度,平坦度纯净度,THD谐波丰富度

2. plotting.py — 可视化(232 行)

5 个函数,统一签名 (result, fig=None) Figure,可被 GUI 嵌入或独立 savefig 导出:

函数 图表 说明
plot_waveform() 波形图 上下双图:整体概览 + 几个周期的细节(自动抽稀防卡顿)
plot_spectrum() 频谱图 幅度谱,标注基频、各次谐波位置、频谱质心
plot_harmonics() 谐波柱状图 各次谐波相对基频百分比,柱上标注数值
plot_spectrogram() 语谱图 时频能量分布 heatmap(scipy spectrogram)
plot_spectrum_comparison() 多文件频谱对比 多条频谱叠加,按各自峰值归一化后对比音色形状

技术细节:

  • 全局配置 rcParams 设置中文字体(Microsoft YaHei / SimHei fallback),支持负号显示
  • 波形抽稀采用均匀步长采样(x[::step]),最大 4000 点
  • 频谱横轴上限自适应:max(F0×12, 2000),不丢高频成分
  • 对比图横轴上限取所有文件奈奎斯特频率的最小值,保证所有曲线完整展示

3. ui/app.py — GUI 界面(401 行)

TimbreApp 类,基于 tkinter + ttk + matplotlib 嵌入。界面布局:


 [选择 CSV 文件…] [导出报告] [打开日志目录] 提示文字   工具栏

 已加载    概览  波形  频谱  谐波  语谱图  对比  
 文件      文字    图像      图像      柱状图    heatmap   叠加谱   
 列表      结论    +工具条   +工具条   +数据表   +工具条   +对比表  
           +表格                                                

 状态栏:就绪 | 日志目录:...                        

关键交互:

  • 多文件加载:一次可选中多个 CSV,后台线程解析分析(threading.Thread),完成后 root.after 回调更新 UI
  • 文件列表切换:左侧 Listbox,点击切换当前查看的文件,自动刷新所有标签页
  • 对比标签页:始终展示全体已加载文件的频谱叠加 + 特征对比表
  • matplotlib 导航工具栏:每个图像标签页附带缩放/平移/保存等标准按钮
  • 导出报告:一键将当前文件的文字结论(.txt)、特征表 + 谐波表(.csv)、4 张图片(.png)写入指定目录
  • 状态栏:实时显示日志目录路径与当前操作状态

4. logging_setup.py — 日志系统(143 行)

自研 DateSizedFileHandler(继承 logging.Handler),核心特性:

特性 实现
按日期分文件 格式 app-YYYY-MM-DD[-N].log
大小轮转 单文件超过 5MB 自动写 -1、-2 后缀文件
过期清理 每次启动时删除 30 天前修改的日志
双通道输出 同时写文件 + 控制台(StreamHandler)
frozen 兼容 打包后 sys._MEIPASS / sys.executable 自适应路径
.env 支持 通过 LOG_LEVEL 环境变量控制日志级别
一键打开目录 open_log_dir() 跨平台(Windows/macOS/Linux)用系统资源管理器打开日志目录

5. main.py — 程序入口(19 行)

configure_logging()  LOGGER.info("启动")  launch_app()  root.mainloop()

同时注册为 pyproject.toml 中的 console_scripts 入口 timbre-analyzer,支持 uv run timbre-analyzer 启动。


分析维度汇总(15 项)

类别 指标 含义
基本信息 采样率、时长、样本数 数据质量参考
时域 RMS 有效值、峰峰值、直流偏置、峰值因数 信号幅度特征
音高 基频 F0(HPS 估计)、音名、音分偏差 音调判断
频谱 质心、带宽、85% 滚降、平坦度、过零率 音色亮度与纯净度
谐波 各次谐波频率与幅值、THD、能量占比 音色厚度与丰富度
主观 亮度/纯净度/谐波丰富度文字描述 人类可读的结论

技术栈

技术 版本 用途
Python 3.12 运行环境
uv latest 包管理、虚拟环境、脚本入口
tkinter / ttk 内置 图形界面(窗口、控件、主题)
numpy 2.5.1 数值计算、FFT 频谱
scipy 1.18.0 信号处理(spectrogram、统计)
matplotlib 3.11.1 图表渲染(嵌入 tkinter)
python-dotenv 1.0.1 .env 环境变量加载
hatchling — 构建系统(pyproject.toml)
PyInstaller 6.21.0 打包成单文件 exe
pytest — 单元测试
ruff / mypy — lint 与类型检查

开发与测试

运行

cd D:\BACKUP\ZF\李伟坚\python-dev_FXYS\timbre_analyzer
uv run timbre-analyzer

测试

uv run pytest -q

3 项测试:

  1. test_estimate_fundamental_frequency — 合成 440Hz 信号,验证 F0 精度 ±3Hz
  2. test_harmonics_and_tables — 合成 200Hz + 2/3 次谐波信号,验证谐波检测与表格生成
  3. test_log_file_name — 验证日志文件名格式

打包

uv run python scripts/build_exe.py

产物:dist/音色分析工具.exe(单文件,~95MB,windowed 模式无控制台)。


输入数据格式

支持 SDS2202X Plus 等示波器导出的 CSV,结构为:

Record Length,Sample Interval, ...
200000,2.5E-05

Source,CH1

Second,Value
-2.499988,-0.000010
-2.499962,-0.000010
...

解析策略:

  1. 扫描元数据行(大小写不敏感匹配 sample interval / source)
  2. 定位数据表头(匹配 second 开头的行)
  3. 若无显式表头,退化扫描第一个可解析为两个浮点数的行
  4. 调用 np.genfromtxt 加载数据列
  5. 采样率优先取元数据中的 Sample Interval 倒数,次选时间列中位数差推导

设计原则

  1. 分层解耦:core 纯计算 plotting 纯绘图 ui 纯界面,三个模块可独立测试和复用
  2. 线程安全:文件解析与分析在后台线程执行,UI 更新通过 root.after 回主线程
  3. 自校验启动:configure_logging() 在 main 入口即调用,任何后续异常都会被日志捕获
  4. frozen 兼容:sys.frozen + sys._MEIPASS 判断,打包后路径自适应
  5. 中文友好:matplotlib 配置中文字体 fallback 链,UI 全中文,CSV 导出使用 UTF-8-BOM 确保 Excel 打开不乱码
  6. 防御性解析:CSV 解析多层 fallback(元数据 表头 退化扫描),单文件失败不影响其他文件继续分析