最近在做一个音频采集识别项目,采集20HZ到20KHZ各个频带最大分贝数(DB),需要用到各个频段的测试音频来验证程序的正确性。
借助Deepseek,原本对python编程没有学过,也能轻松学会。
提问:python生成测试音频文件,需要python专门的编译工具软件吗
以下是DS的回答:
我们使用Python生成测试音频文件,只需要安装几个库即可,不需要专门的编译工具软件。
具体步骤如下:
1. 安装必要的Python库:
- numpy:用于生成音频数据
- soundfile:用于写入WAV文件
2. 可以通过pip安装:
```
pip install numpy soundfile
```
3. 编写Python脚本生成测试音频(如之前提供的脚本)
4. 运行脚本生成WAV文件。
注意:soundfile库在写入WAV文件时,需要依赖libsndfile库。在Windows和macOS上,soundfile通常会自带预编译的库。在Linux上,可能需要安装系统库,例如:
Ubuntu/Debian: `sudo apt-get install libsndfile1`
因此,除了安装Python库,一般不需要其他专门的编译工具软件(除非在Linux上需要安装系统库)。
下面再提供一个完整的测试音频生成脚本,该脚本生成一个包含多个频率成分的音频文件,每个频率成分持续一段时间,便于分段测试。
不需要专门的编译工具软件,只需安装几个 Python 库即可生成测试音频文件。以下是完整的解决方案:
一、所需工具和库
基础要求:
Python 3.6+(官网下载)
pip(Python包管理器,通常随Python安装)
必要库:
bash
pip install numpy scipy soundfile matplotlib
numpy:数值计算库
scipy:科学计算库(用于信号处理)
soundfile:音频文件读写库
matplotlib(可选):用于可视化音频波形
二、完整测试音频生成脚本
python
"""
audio_generator.py - 测试音频生成工具
用于验证ESP32音频分析系统
"""
import numpy as np
import soundfile as sf
import matplotlib.pyplot as plt
import argparse
import sys
def generate_sine_wave(freq, duration=5, sample_rate=48000, amplitude=0.8):
"""生成单频正弦波"""
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
return amplitude * np.sin(2 * np.pi * freq * t)
def generate_test_audio(output_file, sample_rate=48000, duration=10):
"""生成多频带测试音频"""
print(f"生成测试音频: {output_file} (采样率: {sample_rate}Hz, 时长: {duration}秒)")
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
signal = np.zeros_like(t)
# 不同频带的测试信号(带时间标记)
signals = [
{"freq": 50, "start": 0.0, "end": 2.0, "label": "超低频(50Hz)"},
{"freq": 250, "start": 2.0, "end": 4.0, "label": "低频(250Hz)"},
{"freq": 1000, "start": 4.0, "end": 6.0, "label": "中低频(1kHz)"},
{"freq": 2500, "start": 6.0, "end": 8.0, "label": "中频(2.5kHz)"},
{"freq": 5000, "start": 8.0, "end": 10.0, "label": "中高频(5kHz)"},
{"freq": 10000, "start": 10.0, "end": 12.0, "label": "高频(10kHz)"},
{"freq": 15000, "start": 12.0, "end": 14.0, "label": "超高频(15kHz)"},
{"freq": 18000, "start": 14.0, "end": 16.0, "label": "极高频(18kHz)"}
]
# 组合信号
for s in signals:
start_idx = int(s["start"] * sample_rate)
end_idx = int(s["end"] * sample_rate)
segment = generate_sine_wave(s["freq"], s["end"]-s["start"], sample_rate)
signal[start_idx:end_idx] += segment[:end_idx-start_idx]
# 归一化防止削波
signal = 0.8 * signal / np.max(np.abs(signal))
# 保存为WAV文件
sf.write(output_file, signal, sample_rate, subtype='PCM_16')
print(f"成功生成测试音频: {output_file}")
return signal
def plot_audio_waveform(signal, sample_rate, output_image=None):
"""可视化音频波形(可选)"""
plt.figure(figsize=(12, 6))
plt.title("测试音频波形")
plt.plot(np.arange(len(signal)) / sample_rate, signal)
plt.xlabel("时间 (秒)")
plt.ylabel("振幅")
plt.grid(True)
if output_image:
plt.savefig(output_image)
print(f"波形图保存至: {output_image}")
else:
plt.show()
def main():
parser = argparse.ArgumentParser(description='ESP32音频分析系统测试音频生成工具')
parser.add_argument('-o', '--output', default='audio_test.wav', help='输出WAV文件名')
parser.add_argument('-s', '--sample-rate', type=int, default=48000, help='采样率 (默认48000)')
parser.add_argument('-d', '--duration', type=int, default=16, help='音频时长(秒) (默认16)')
parser.add_argument('-p', '--plot', metavar='IMAGE', help='生成波形图(可选)')
args = parser.parse_args()
try:
signal = generate_test_audio(args.output, args.sample_rate, args.duration)
if args.plot:
plot_audio_waveform(signal, args.sample_rate, args.plot)
print("\n使用说明:")
print("1. 将此音频文件复制到手机/电脑")
print("2. 在安静环境中播放音频")
print("3. 将ESP32的麦克风靠近扬声器")
print("4. 监控串口输出,验证各频段检测结果")
except Exception as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
三、使用说明
安装依赖库:
bash
pip install numpy scipy soundfile matplotlib
生成测试音频:
bash
# 基本用法
python audio_generator.py
# 自定义输出文件
python audio_generator.py -o custom_test.wav
# 生成波形图
python audio_generator.py -p waveform.png
输出文件:
audio_test.wav:16秒测试音频,包含8个频段
waveform.png(可选):音频波形可视化
四、音频内容说明
生成的测试音频包含以下分段信号:
时间段(秒) 频率(Hz) 频带类别 预期检测频带
0-2 50 超低频 12-100Hz
2-4 250 低频 100-500Hz
4-6 1000 中低频 500-2000Hz
6-8 2500 中频 2000-3000Hz
8-10 5000 中高频 3000-8000Hz
10-12 10000 高频 8000-12000Hz
12-14 15000 超高频 12000-16000Hz
14-16 18000 极高频 16000-20000Hz
五、验证方法
播放音频:
使用任何媒体播放器(VLC、Windows Media Player等)
确保扬声器/耳机质量可以播放18kHz高频
监控ESP32输出:
每秒应看到对应频带的峰值升高
示例输出:
[0-2秒] 12-100Hz频带值显著高于其他
[2-4秒] 100-500Hz频带值显著高于其他...
特殊验证技巧:
python
# 生成纯18kHz测试音
python -c "import numpy as np; import soundfile as sf; t=np.linspace(0,5,240000); sf.write('18khz.wav', 0.8*np.sin(2*np.pi*18000*t), 48000)"
播放此文件时,应只有16000-20000Hz频带有显著输出
六、常见问题解决
高频无法播放:
使用频谱分析APP(如Spectroid)检查手机扬声器输出
更换高质量耳机/扬声器
库安装失败:
bash
# Windows用户尝试
python -m pip install --upgrade pip
pip install wheel
pip install numpy scipy soundfile
# macOS/Linux用户
pip3 install numpy scipy soundfile
音频生成失败:
确保有足够的磁盘空间
尝试降低采样率:python audio_generator.py -s 44100
这个方案完全基于Python标准工具链,无需任何专业音频设备或商业软件,即可生成用于验证ESP32音频分析系统的测试文件。
上述是DS的回答,但上述的生成的完整脚本,因为带有中文注解,在WINDOS执行脚本,会执行出错,需要多一个提问,即可生成完整可执行的脚本。
提问:把上文中提到的完整测试音频生成脚本,把中文部分脚本转成英文脚本。
DS回答:
We are going to translate the entire script to English, including comments, strings, and variable names (where appropriate). However, we will keep the function and variable names in English but without translating them if they are already in a technical context. The main goal is to have the script in English for better international readability.
Steps:
1. Translate the comments to English.
2. Translate the strings (like print statements) to English.
3. Keep function and variable names in English (they are already in English).
4. The structure and logic of the code remain the same.
Let's do it step by step.
Here's the fully translated English version of the test audio generation script:
python
"""
audio_generator.py - Test Audio Generator
For validating ESP32 audio analysis systems
"""
import numpy as np
import soundfile as sf
import matplotlib.pyplot as plt
import argparse
import sys
def generate_sine_wave(freq, duration=5, sample_rate=48000, amplitude=0.8):
"""Generate a sine wave at specified frequency"""
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
return amplitude * np.sin(2 * np.pi * freq * t)
def generate_test_audio(output_file, sample_rate=48000, duration=10):
"""Generate multi-band test audio"""
print(f"Generating test audio: {output_file} (Sample rate: {sample_rate}Hz, Duration: {duration} seconds)")
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
signal = np.zeros_like(t)
# Test signals for different frequency bands (with timing markers)
signals = [
{"freq": 50, "start": 0.0, "end": 2.0, "label": "Sub-bass (50Hz)"},
{"freq": 250, "start": 2.0, "end": 4.0, "label": "Bass (250Hz)"},
{"freq": 1000, "start": 4.0, "end": 6.0, "label": "Low-mid (1kHz)"},
{"freq": 2500, "start": 6.0, "end": 8.0, "label": "Mid-range (2.5kHz)"},
{"freq": 5000, "start": 8.0, "end": 10.0, "label": "Upper-mid (5kHz)"},
{"freq": 10000, "start": 10.0, "end": 12.0, "label": "Presence (10kHz)"},
{"freq": 15000, "start": 12.0, "end": 14.0, "label": "Brilliance (15kHz)"},
{"freq": 18000, "start": 14.0, "end": 16.0, "label": "Ultra-high (18kHz)"}
]
# Combine signals
for s in signals:
start_idx = int(s["start"] * sample_rate)
end_idx = int(s["end"] * sample_rate)
segment = generate_sine_wave(s["freq"], s["end"]-s["start"], sample_rate)
signal[start_idx:end_idx] += segment[:end_idx-start_idx]
# Normalize to prevent clipping
signal = 0.8 * signal / np.max(np.abs(signal))
# Save as WAV file
sf.write(output_file, signal, sample_rate, subtype='PCM_16')
print(f"Test audio successfully generated: {output_file}")
return signal
def plot_audio_waveform(signal, sample_rate, output_image=None):
"""Visualize audio waveform (optional)"""
plt.figure(figsize=(12, 6))
plt.title("Test Audio Waveform")
plt.plot(np.arange(len(signal)) / sample_rate, signal)
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude")
plt.grid(True)
if output_image:
plt.savefig(output_image)
print(f"Waveform saved to: {output_image}")
else:
plt.show()
def main():
parser = argparse.ArgumentParser(description='Test Audio Generator for ESP32 Audio Analysis Systems')
parser.add_argument('-o', '--output', default='audio_test.wav', help='Output WAV filename')
parser.add_argument('-s', '--sample-rate', type=int, default=48000, help='Sample rate (default 48000)')
parser.add_argument('-d', '--duration', type=int, default=16, help='Audio duration in seconds (default 16)')
parser.add_argument('-p', '--plot', metavar='IMAGE', help='Generate waveform plot (optional)')
args = parser.parse_args()
try:
signal = generate_test_audio(args.output, args.sample_rate, args.duration)
if args.plot:
plot_audio_waveform(signal, args.sample_rate, args.plot)
print("\nUsage instructions:")
print("1. Copy this audio file to your phone/computer")
print("2. Play the audio in a quiet environment")
print("3. Position ESP32's microphone near the speaker")
print("4. Monitor serial output to verify band detection")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
将上述脚本复制到一个文本文档,然后保存成py后缀名的python脚本,放在相当应的目录下,在此目录下运行CMD命令,按照DS的提示的python脚本,即可生成想要的对应音频文件。