PESQ源码编译与运行实战:从Makefile到MOS分全流程解析

发布时间:2026/10/22 3:33:57
PESQ源码编译与运行实战:从Makefile到MOS分全流程解析 简介PESQ工具编译源码包内含语音质量评估工具PESQ的完整编译源码与配套资料面向音频编码、通信系统测试、语音增强等领域的开发者和研究者可用于客观量化语音质量、对比不同处理算法的效果。资源包共88个文件压缩包约5.53MB核心为C/C源码5个.c与3个.h以及编译生成的可执行文件pesq另包含66个wav测试语音、6个txt说明文档、2个bat批处理脚本、P.862标准PDF和WORD说明文档构成一套可直接学习与实验的完整环境。目前已有655人学习下载。随包附带的源码编译教程覆盖了GCC/MinGW环境配置、Makefile修改以及make编译等关键步骤使用教程则详细说明参考语音与待测语音的输入方式、窄带/宽带模式参数及MOS评分结果解读。借助内置的wav样本读者可快速复现PESQ评测流程为相关算法开发提供量化依据。1. 为什么要自己编译 PESQ一个 make 就能完成却卡住不少项目A同学最近在做语音增强方案选型需要把处理前后的语音转成可对比的客观分数。他拿到一份 PESQ 工具源码包后在服务器上敲了 make结果被一串编译报错卡了两天。类似的情况并不少见PESQ 是语音质量评价里常用的工具通过对比参考语音和处理后语音给出一个可复现的 MOS 分直接找现成可执行文件固然省事但在内网环境、老旧服务器或需要改动音频预处理逻辑的场景里自己从源码编译 PESQ 才是可靠路径。正常环境下一两分钟能出结果真正耗时间的往往是 Makefile 里的编译选项和音频格式检查。下面从源码结构讲起把编译命令、运行参数和典型的编译运行问题梳理清楚目标是让你从解压一路跑到第一次打分。2. PESQ 在算什么源码结构、输入音频格式与分数含义2.1 从波形到 MOS 分PESQ 的处理链路PESQ 本质是一套把主观听感转成可重现分数的算法。它的输入是两段语音一段是参考一段是待评估的退化语音。算法会先把两段信号做电平调整和时延对齐然后用一组模拟人耳频率分辨特性的滤波器组把信号拆分到多个频带再把频带能量映射到响度标尺逐帧计算扰动密度最后把坏区间加权聚合成一个分数。语音增强前后的差异在波形上可能很大但人耳对某些失真不敏感PESQ 的感知域处理正好能把这部分差异抹平这是它比简单算 SNR 更贴近主观听感的原因。实际编译使用时不需要记住每个数学公式但必须清楚三个边界其一必须有参考信号单端场景不能直接用 PESQ其二输出分数适合做相对对比比如同一参考下比较算法 A 和算法 B而不是跨数据集比较绝对值其三时延和对齐高度敏感输入文件里多余的前导静音会让分数偏离预期。我在编解码器评估、VoIP 语音质量和语音增强回归测试里都用它选型阶段看趋势上线前再辅以主观听测。如果只需要“分越低越差”的排序能力PESQ 的数学细节可以当作黑匣子但输入格式和分数边界不能黑匣子。2.2 源码包里的文件分工p862、dsp 与 Makefile从源码包做编译第一步不是敲 make而是打开看文件清单。一份典型的 PESQ 源码包里有 p862.c 和 p862.h这是语音质量客观评估标准里核心算法实现dsp.c 与 dsp.h 提供滤波器组、FFT 等基础运算pesqmain.c 负责命令行入口处理参数、读文件、调用核心接口并打印分数最后还会有一个 Makefile 把编译链接串起来。我见过不少人在没有 Makefile 的残缺包里硬编最后手动拼了一长串 gcc 命令所以先确认文件齐不齐很有必要。tar -xzf pesq_source.tar.gz cd pesq_source ls -l *.c *.h Makefile这段命令把压缩包解压并列出源码文件。逻辑说明tar -xzf 解压并保持文件权限ls -l 看文件大小和时间戳如果连 Makefile 都没有说明这份源码不完整需要自己补一条编译规则。参数说明这里的压缩包名只是我这次拿到的样本实际以你手里的文件名为准。接着我习惯用 grep 扫一眼 Makefile 里的关键编译选项grep -nE CFLAGS|LDFLAGS|LIBS|-m32|-m64|-lm Makefile逻辑说明grep 只保留和编译选项有关的行避免在一大段 Makefile 里来回翻。参数说明CFLAGS 决定优化级别和目标架构-m32、-m64 决定编译成 32 位还是 64 位-lm 决定是否链接数学库这几项就是稍后编译能否一次通过的关键。PESQ 原版源码是较早的 C 代码风格对优化等级不敏感O0 和 O2 跑出的分数没有可感知差异所以不要在优化参数上纠结。2.3 输入要求与输出字段先让格式可控分数才有意义PESQ 的分数可信度有一大半取决于输入音频是否规范。原版窄带实现要求 8kHz、16 bit、单声道 PCM扩展版本支持 16kHz但必须显式传采样率参数。我一般先把候选音频用 file 命令检查一遍file ref.wav deg.wav逻辑说明file 会输出采样宽度、通道数和采样率。如果看到 PCM 16-bit signed audio 且采样率是 8000 Hz 的描述说明格式基本合格。参数说明如果显示 floating-point 或 32-bitPESQ 内置的读文件逻辑很可能直接解析失败。假如手头只有 16kHz 或浮点 WAV常见做法是用 sox 先统一格式sox 16k_in.wav -r 8000 -c 1 -b 16 ref.wav sox 16k_in.wav -r 8000 -c 1 -b 16 deg.wav这段命令把源音频重采样到 8kHz、转成单声道、量化到 16bit。逻辑说明-r 8000 指定采样率-c 1 强制单声道-b 16 指定位深参考和退化必须用同一条命令处理避免格式规整引入额外差异。参数说明sox 不是 PESQ 的依赖只是做预处理没有 sox 的机器可以用熟悉的音频工具完成同样转换。命令行输出因源码包打印逻辑不同而略有差异常见会出现类似 PESQ_MOS 3.124 的行。拿到分数前先做一次自检把同一个文件既当参考又当退化得分应该落在接近满分的区间。这一步能过滤掉大多数格式问题。如果同一个文件打分明显偏低问题基本不在算法而在你给它的输入不是它想要的东西。3. Linux 下编译 PESQ 源码从解压到跑通第一次评测3.1 编译前的环境检查gcc、make 与系统位数PESQ 源码依赖很少只要 gcc 和 make 存在就能编。先做两个检查避免把系统问题误判成源码问题。检查gcc --version make --version逻辑说明有版本输出就说明工具装好了如果提示 command not found先安装基础开发工具。参数说明gcc 的版本不影响最终分数旧版本和高版本都能编译只是老代码偶尔需要兼容选项。再确认系统位数uname -m逻辑说明x86_64 表示 64 位i386 或 i686 表示 32 位。这个信息用来判断源码包里的 -m32 选项是否会造成麻烦。参数说明如果系统是 64 位而 Makefile 强制编 32 位现代发行版经常缺少 32 位头文件而直接报错PESQ 核心是浮点运算编成 64 位对结果没有影响所以一个稳妥做法是把目标改成 64 位。3.2 修改 Makefile去掉 -m32补上 -lm这一步是很多人翻车的根源。有的源码包为了兼容老环境在 CFLAGS 里写死 -m32在 64 位系统上必然出问题。我一般会先把 Makefile 打开看几个关键行vim Makefile重点看 CFLAGS 是否有 -m32以及最终的链接规则里是否出现 -lm。如果发现强制 32 位用 sed 一次替换sed -i s/-m32/-m64/g Makefile逻辑说明sed -i 直接改写文件把强制 32 位改成 64 位。若替换后仍然报头文件缺失就把这个编译选项彻底删掉。参数说明部分源码包把 -m32 写在一个变量里替换后要用 grep 再确认生效。链接行缺 -lm 的情况同样常见。PESQ 计算里用到 pow、sqrt 等数学函数如果最终链接命令末尾没有 -lm会在链接阶段报 undefined reference。手写链接命令时规范写法是gcc -O2 -o pesq p862.o dsp.o pesqmain.o -lm这行把三个目标文件链接成 pesq 可执行文件-O2 只是常规优化-lm 是关键。逻辑说明-lm 位于目标文件之后链接器按顺序解析符号参数说明如果源码包提供了 Makefile可以简单地在 LIBS 变量里追加 -lm不必逐个手敲。3.3 编译与生成make clean 与 makeMakefile 调整完成进入编译。我总是先做 make clean 再做 make。理由很直接上一次失败可能留下带错误编译选项的 .o 文件直接 make 可能让这次的链接沿用旧产物产生“明明改了还报错”的错觉。make clean make逻辑说明make clean 清理由上轮产生的目标文件和可执行文件make 按 Makefile 规则逐个编译源文件并链接。如果源码包没有 Makefile就用手写的 gcc -O2 -c 编译每个 .c再执行上面的链接命令。参数说明make 过程中如果某条规则缺失不要硬改源文件优先检查文件名大小写和 Makefile 里的依赖关系。编译完成后检查产物file pesq逻辑说明输出 ELF 64-bit 之类的架构信息说明链接成功常见的失败是提示无权限或输出文件为零字节。参数说明这里的架构信息应该和 uname -m 一致不一致时回头排查 Makefile 的位数选项。3.4 首次运行用 8kHz WAV 试通 8000 参数编译成功不代表评测链路通。第一次运行我习惯用同一个文件当参考和退化./pesq 8000 ref.wav ref.wav逻辑说明参考等于退化分数应当接近 PESQ 的上限通常在 4.5 附近这一步能一次性验证音频格式、采样率参数和核心算法调用链。参数说明8000 指示按 8kHz 解析如果音频是 16kHz这里必须对应改成 16000前提是你拿到的版本支持宽带采样率。自检通过后构造一个轻度失真样本看分数是否响应sox ref.wav -r 8000 -c 1 -b 16 noisy.wav vol 0.7 ./pesq 8000 ref.wav noisy.wav逻辑说明vol 0.7 把音量降到原来的七成参考不变退化的分数应当明显低于第一次。参数说明如果两次分数完全相同多半是第二个文件路径写错或者退化和参考实际读取到了同一个文件。这一步通过就说明编译出来的可执行文件可以进入真实评测了。4. PESQ 编译与运行排查5 类高频问题与解决编译 PESQ 的报错类型很集中大多数与算法本身无关而是 Makefile 选项、缺失的数学库、音频格式和参数顺序。下面按现象到原因再到解决办法的方式列出 5 类我在给人排查时见过最多的问题基本都是血泪经验换来的。4.1 现象 1make 报错 sys/cdefs.h 不存在现象在 64 位 Linux 上直接 make编译器报 fatal error: sys/cdefs.h: No such file or directory随后中断。原因Makefile 里 CFLAGS 带了 -m32编译器按 32 位目标去找头文件而现代发行版的 64 位开发环境里没有那套 32 位头文件。这属于编译选项与系统环境不匹配不是源码缺文件。解决把 Makefile 里的 -m32 改成 -m64 或直接删除改完必须 make clean再重新 make。sed -i s/-m32/-m64/g Makefile make clean make逻辑说明sed 替换编译选项后clean 和 make 一次性串起来执行。参数说明如果 sed 没匹配到用 grep -n m32 确认目标行再手工编辑。注意这是源码包预设编译目标与当前系统架构不匹配不要尝试去系统目录里补 32 位头文件改编译选项更省事。4.2 现象 2链接报 undefined reference to sqrt现象编译阶段正常链接阶段报 undefined reference to sqrt、undefined reference to pow 这类符号缺失。原因PESQ 计算里用到了数学库函数但链接命令行里缺少 -lm。部分源码包的 Makefile 自带 -lm但有些整理过的版本把它漏掉了或者你手写的链接命令没带。解决在链接行末尾追加 -lm。如果 Makefile 里有 LIBS 变量直接在变量里追加如果是手写命令按下面的形式执行gcc -O2 -o pesq p862.o dsp.o pesqmain.o -lm逻辑说明-lm 放在目标文件后面才能正确解析数学符号放在最前面有时会因链接顺序导致依旧报错。参数说明如果你的源码包目标文件名和列出的不一样先用 ls *.o 看当前目录下的实际产物。4.3 现象 3运行时提示无法打开 wav 文件或格式解析失败现象./pesq 运行时提示文件打不开或者文件能打开但直接报音频格式错误检查后发现文件明明存在。原因最常见是命令行参数顺序不对。PESQ 的用法是先传采样率再传参考文件最后传退化文件。其次是音频不是 16bit PCM 单声道 WAVPESQ 自带的读文件逻辑对格式很挑剔。解决先用绝对路径排除目录问题再确认参数顺序最后用 file 检查格式。/path/to/pesq 8000 /path/to/ref.wav /path/to/deg.wav file /path/to/ref.wav /path/to/deg.wav逻辑说明第一条确保路径不依赖当前目录第二条确认两路输入都是 16bit 单声道 PCM。参数说明如果 file 显示的是 24bit 或浮点格式先用 sox 转成 16bit 再跑。4.4 现象 4拿同一文件做参考和退化分数远低于 4.5现象自检时预期分数在 4.5 附近实际却只有 3 点几甚至更低。原因音频看似是 wav实际是浮点采样或 24bit 位深PESQ 读文件时按 16bit 解析发生了位宽错位也可能是音频本身是 16kHz但命令行仍用 8000导致算法按错误的采样率去算时长和帧数。解决把参考和退化都用同一套 sox 命令规整到 8kHz、16bit、单声道并让命令行里的采样率参数与文件实际采样率一致。sox ref.src.wav -r 8000 -c 1 -b 16 ref.wav sox deg.src.wav -r 8000 -c 1 -b 16 deg.wav ./pesq 8000 ref.wav deg.wav逻辑说明前两条统一格式第三条按统一后的采样率打分。参数说明如果你的源码包支持 16kHz可以直接用 16000但前提是参考和退化都真的是 16kHz 采样率。4.5 现象 5分数出现负数或极端小值现象打分结果出现 -0.5 附近的数值或者两份差异不大的样本分数突然跳变到极低值。原因PESQ 原始分数的范围本身包含负数出现负值不一定是 bug但极端小值往往来自参考和退化的时延差异过大或者输入时长太短算法统计的帧数不足坏区间权重被放大。解决先检查输入时长短句补静音到至少 2 秒以上再检查参考和退化是否有额外前导静音有则裁剪到同一偏移位置后重测。soxi -D ref.wav soxi -D deg.wav逻辑说明soxi -D 输出音频时长对比两个文件时长差。参数说明如果时长差超过 0.5 秒优先考虑对齐问题而不是怀疑算法分数PESQ 内置对齐能处理一定程度的时延但超过阈值后分数会明显失真。5. 跑通只是开始把 PESQ 编进批量语音评测流程编译完成的 PESQ 一次只能处理一对文件。实际评测里有几十上百条语音等着打分我习惯把它包进一个 bash 脚本循环处理同一目录下的参考和处理结果。#!/bin/bash REF_DIRref_wav DEG_DIRdeg_wav for f in $REF_DIR/*.wav; do name$(basename $f) echo $name ./pesq 8000 $REF_DIR/$name $DEG_DIR/$name done逻辑说明脚本遍历 ref_wav 下每个 wav取文件名后到 deg_wav 里找同名文件逐对调用 PESQ。参数说明目录后有空格时双引号能防止路径解析出错这是批量脚本最容易忽略的细节。如果只需要把 MOS 分收集成表格可以用 grep 和 awk 提取输出行for f in ref_wav/*.wav; do n$(basename $f) score$(./pesq 8000 ref_wav/$n deg_wav/$n 2/dev/null | grep -o PESQ_MOS [0-9.-]* | awk {print $3}) echo $n,$score done scores.csv逻辑说明grep -o 只抓分数行awk 取第三个字段得到数值单条评测失败时 score 为空脚本也不会中断。参数说明2/dev/null 丢弃 PESQ 打印的附加信息只保留标准输出中的分数行。批量跑完后不要直接拿分数上报。挑几个极端样本听一下PESQ 对静音、音乐信号、强背景噪声的鲁棒性有限某个算法分数大幅提升并不意味着听感一定更好。我通常把 PESQ 分数和主观听测放在一起看分数只用来筛选候选方案不直接作为验收依据。有个习惯保留到现在拿到语音评测工具源码先编译再同文件自检最后构造一个失真样本看分数是否下降。这套流程能过滤掉一大半的假阳性结果。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询