2. 语音信号基础

说实话,做语音算法部署,最怕的不是算法调不通,而是环境先崩了。我见过太多同学花了两天装依赖,最后发现 Python 版本不对,或者 libsndfile 没装,连个 wav 都读不出来。所以这一章,咱们先把台面擦干净。

我个人习惯,每个项目都开独立的虚拟环境。为什么?因为 numpy、scipy 这些库版本一乱,你后面跑 WebrtcVAD 或者 librosa 的时候,报错会让你怀疑人生。我曾经在一个项目里同时维护三个环境,就因为客户那边 Python 3.6 死活升不上去…嗯,从那以后我学乖了。

2.1 Python 虚拟环境配置

虚拟环境说白了就是给你的项目一个“隔离的小房间”。你在这个房间里装什么库,都不会影响到系统全局或者其他项目。

我推荐用 venv,Python 3.3+ 自带,不需要额外装东西。操作很简单:

# 创建虚拟环境(在项目根目录下执行)
python -m venv denoise_env

# 激活环境(Windows)
denoise_env\Scripts\activate

# 激活环境(macOS/Linux)
source denoise_env/bin/activate

激活后,你会看到终端前面多了个 (denoise_env) 前缀。这时候你 pip install 的任何东西,都只装在这个环境里。

小技巧: 我习惯在项目根目录下建一个 .venv 文件夹,然后把它加到 .gitignore 里。这样团队其他人 clone 代码后,自己重新建环境就行,不会把一堆二进制文件传到仓库里。

2.2 依赖库安装与版本说明

咱们这个课程要用到的核心库,我列了个表。每个库的用途和推荐版本,你照着装就行。

库名 版本(推荐) 用途
numpy ≥1.21.0 数组运算、矩阵操作,语音信号本质就是数组
scipy ≥1.7.0 信号处理函数(滤波器设计、FFT、插值)
soundfile ≥0.12.0 读写 wav/flac/ogg 等音频文件,底层依赖 libsndfile
librosa ≥0.9.0 音频分析(频谱、MFCC、重采样),功能很全
webrtcvad ≥2.0.10 WebRTC 语音活动检测,判断一段音频里有没有人声

安装命令也很直接:

pip install numpy==1.21.0 scipy==1.7.0 soundfile==0.12.0 librosa==0.9.0 webrtcvad==2.0.10

如果你不想纠结版本号,直接 pip install numpy scipy soundfile librosa webrtcvad 也行,但建议装完后用 pip freeze 看一下实际版本,方便后面排查问题。

注意: soundfile 在 Windows 上可能需要额外安装 libsndfile 的二进制文件。如果你遇到 OSError: sndfile library not found,去 libsndfile-binaries 下载对应系统的 dll,放到 Python 的 DLLs 目录下就行。macOS 和 Linux 一般自带,或者 brew install libsndfile / apt install libsndfile1 搞定。

2.3 音频文件读写与播放验证

环境搭好了,咱们得验证一下能不能正常工作。我一般会写一个简单的测试脚本,读一个 wav 文件,打印基本信息,再写回去,最后用播放器听一下。

下面这个脚本,你直接复制到 test_audio_io.py 里跑就行:

import soundfile as sf
import numpy as np
import librosa

# 1. 用 soundfile 读取音频
file_path = "test.wav"  # 你自己准备一个 wav 文件
data, sr = sf.read(file_path)
print(f"采样率: {sr} Hz")
print(f"数据形状: {data.shape}")
print(f"数据类型: {data.dtype}")
print(f"时长: {len(data)/sr:.2f} 秒")

# 2. 用 librosa 读取(会自动重采样到指定 sr)
data_lib, sr_lib = librosa.load(file_path, sr=16000)
print(f"\nlibrosa 重采样后采样率: {sr_lib} Hz")
print(f"librosa 数据形状: {data_lib.shape}")

# 3. 生成一个简单的正弦波并保存
t = np.linspace(0, 1, sr, endpoint=False)
sine_wave = 0.5 * np.sin(2 * np.pi * 440 * t)  # 440Hz A4 音
sf.write("sine_440.wav", sine_wave, sr)
print("\n已生成 sine_440.wav,你可以用播放器听一下")

跑完这个脚本,你应该能看到类似这样的输出:

采样率: 44100 Hz
数据形状: (132300,)
数据类型: float64
时长: 3.00 秒

librosa 重采样后采样率: 16000 Hz
librosa 数据形状: (48000,)

已生成 sine_440.wav,你可以用播放器听一下

如果一切顺利,恭喜你,环境搭建成功了。如果报错,别慌,大概率是某个库没装好,或者文件路径不对。检查一下 pip list 看看库有没有在虚拟环境里。

核心要点:
  • 虚拟环境是隔离项目依赖的第一道防线,每个项目都该有自己的环境
  • soundfile 和 librosa 都能读写音频,但 librosa 默认会重采样到 22050Hz,注意这个行为差异
  • 写回文件时,sf.write 的采样率参数必须和原始数据匹配,否则播放会变调

2.4 本章知识体系总览

下面这张图,把咱们这一章的核心流程串起来了。从创建虚拟环境开始,到装依赖,再到读写验证,每一步都是后面做降噪算法的基础。

环境搭建与工具链流程图 环境搭建与工具链核心流程 创建虚拟环境 python -m venv denoise_env 激活虚拟环境 source denoise_env/bin/activate 安装依赖库 pip install numpy scipy ... 音频文件读取 soundfile / librosa 数据处理与验证 打印信息 / 生成测试音 音频文件写入 sf.write() 保存 💡 说明 • 虚拟环境隔离项目依赖,避免版本冲突 • soundfile 和 librosa 都能读写音频,但 librosa 默认重采样到 22050Hz

你看,整个流程其实就三步:建环境、装库、验证读写。但就是这三步,决定了你后面所有算法能不能跑起来。我见过太多人跳过验证这一步,结果写到一半发现 librosa 读出来的数据和 soundfile 不一样,又回头排查…浪费时间。

所以,我的建议是:每次换机器或者换项目,都跑一遍这个测试脚本。花不了两分钟,但能帮你省下后面两小时的 debug 时间。