借助DS用python帮你编写脚本(辅助开发测试)

发布于:2025-05-31 ⋅ 阅读:(23) ⋅ 点赞:(0)

最近在做一个音频采集识别项目,采集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脚本,即可生成想要的对应音频文件。


网站公告

今日签到

点亮在社区的每一天
去签到