Elephant 在「实现音频波形可视化器」的评测结果

这是该 AI 模型在此测试用例上的详细评测结果。

基本信息

  • 模型名称:Elephant
  • 用例名称:实现音频波形可视化器
  • 测试类型:文本生成
  • 评测维度:代码生成

系统提示词(System Prompt)

这是给 AI 模型的背景设定和角色指令:

你是一名资深音频软件工程师,擅长使用 Python 进行音频处理与数据可视化。 回答要求: 1. 使用 Python 标准库 `wave` 读取 WAV 文件,使用 `matplotlib` 生成波形图,不依赖非必要的第三方库。 2. 代码需结构清晰,包含必要的注释,说明关键步骤(如采样率获取、PCM 数据解码、归一化处理)。 3. 实现缩放功能时,需支持通过参数指定显示的时间范围(起始秒数与结束秒数)。 4. 输出代码需可直接运行,并附带简要的使用说明。 5. 对异常情况(如文件不存在、格式不支持)需有基本的错误处理。

用户提示词(User Prompt)

这是用户给 AI 模型的具体任务要求:

请使用 Python 实现一个简单的 WAV 音频波形静态可视化工具。 **功能要求:** 1. **读取 WAV 文件**:使用 Python 内置 `wave` 模块读取指定路径的 WAV 格式音频文件,并打印基本信息(采样率、声道数、采样位深、总帧数、时长)。 2. **提取采样数据**:将原始 PCM 字节数据解码为数值数组(使用 `numpy` 或 `struct`),并对数据进行归一化处理(将幅度缩放到 [-1.0, 1.0] 范围)。 3. **生成静态波形图**:使用 `matplotlib` 绘制时域波形图,横轴为时间(秒),纵轴为归一化幅度,图表需包含标题、轴标签和网格线。 4. **支持基本缩放**:实现一个函数,接受 `start_sec` 和 `end_sec` 参数,仅显示指定时间范围内的波形,若参数为 `None` 则显示完整波形。 **技术约束:** - 语言:Python 3.8+ - 允许使用的库:`wave`(标准库)、`struct`(标准库)、`numpy`、`matplotlib` - 需处理单声道和立体声(多声道取第一声道显示) - 需处理 8-bit 和 16-bit 两种常见采样位深 **输出要求:** - 提供完整可运行的 Python 代码 - 提供一个 `visualize_waveform(filepath, start_sec=None, end_sec=None)` 函数作为主入口 - 在代码末尾附上使用示例(`if __name__ == 「__main__」:` 块)

任务要求

AI 模型需要满足以下要求:

  1. 正确使用 `wave` 模块读取 WAV 文件元数据(采样率、声道数、位深、帧数),并能据此还原时间轴。
  2. 正确将 PCM 字节数据解码为数值数组,并执行归一化处理(8-bit 数据需减去 128 再除以 128,16-bit 数据除以 32768)。
  3. 多声道音频能正确提取单一声道(如第一声道),不将多声道数据混叠显示。
  4. 「`start_sec` / `end_sec` 缩放参数能正确截取对应帧范围的数据,边界值(如超出范围)需有合理处理。」
  5. 波形图包含正确的时间轴(单位:秒)、归一化幅度轴、图表标题、轴标签及网格线。
  6. 对文件不存在或非 WAV 格式等异常情况有基本的错误处理(try/except 并给出提示信息)。

评测结果

综合得分

该模型在此用例的得分为:84.3 分(满分 100 分),已通过

基础难度评测结果

  • 得分:84.3 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

```python import wave import struct import numpy as np import matplotlib.pyplot as plt def visualize_waveform(filepath, start_sec=None, end_sec=None): """ 可视化 WAV 音频文件的时域波形图。 参数: filepath (str): WAV 文件路径 start_sec (float or None): 显示起始时间(秒),None 表示从开头开始 end_sec (float or None): 显示结束时间(秒),None 表示到结尾结束 """ try: # --- 1. 打开并读取 WAV 文件基本信息 --- with wave.open(filepath, 'rb') as wf: # 获取音频参数 n_channels = wf.getnchannels() # 声道数(1=单声道, 2=立体声) sample_width = wf.getsampwidth() # 采样位深(字节数),如 1=8bit, 2=16bit framerate = wf.getframerate() # 采样率(Hz),如 44100 n_frames = wf.getnframes() # 总帧数 comptype = wf.getcomptype() # 压缩类型,应为 'NONE' compname = wf.getcompname() # 压缩名称,应为 'not compressed' # 打印基本信息 duration = n_frames / framerate print(f"文件: {filepath}") print(f" 声道数: {n_channels}") print(f" 采样率: {framerate} Hz") print(f" 采样位深: {sample_width * 8} bit") print(f" 总帧数: {n_frames}") print(f" 时长: {duration:.3f} 秒") # 检查压缩格式(仅支持无损) if comptype != 'NONE': raise ValueError(f"不支持压缩格式: {comptype} ({compname})") # --- 2. 读取并解码 PCM 数据 --- # 读取原始字节数据 pcm_data = wf.readframes(n_frames) # 将字节数据转换为数值数组 # struct 格式说明: # ' 1: # 重塑为 (n_frames, n_channels),然后取第0列 audio_data = audio_data.reshape(-1, n_channels)[:, 0] print(f" (已提取第一声道数据)") # --- 3. 处理显示时间范围 --- total_duration = len(audio_data) / framerate # 确定显示范围 if start_sec is None: start_idx = 0 else: if start_sec = total_duration: raise ValueError(f"起始时间 {start_sec} 超出音频范围 [0, {total_duration:.3f}]") start_idx = int(start_sec * framerate) if end_sec is None: end_idx = len(audio_data) else: if end_sec total_duration: raise ValueError(f"结束时间 {end_sec} 超出音频范围 [0, {total_duration:.3f}]") if end_sec <= start_sec: raise ValueError("结束时间必须大于起始时间") end_idx = int(end_sec * framerate) # 提取子集 display_data = audio_data[start_idx:end_idx] display_times = np.arange(start_idx, end_idx) / framerate # --- 4. 绘制波形图 --- plt.figure(figsize=(12, 5)) plt.plot(display_times, display_data, color='b', linewidth=0.5) plt.title(f'Waveform: {filepath}') plt.xlabel('Time...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【GEMINI】这是一份高质量的代码实现,展示了候选人对音频底层数据结构(PCM 编码、位深、声道布局)的深刻理解。代码在数学逻辑和架构设计上几乎完美,特别是对 8-bit 和 16-bit 归一化的处理非常专业。唯一的遗憾是 `struct.unpack` 的格式化字符串拼接漏掉了类型字符 `dtype`(应为 `<1000h` 而非 `<1000`),导致程序在执行核心解码步骤时会报错。修复此小问题后,该代码将是该任务的模范解答。 【KIMI】整体而言,代码实现了WAV音频波形可视化的核心功能,包括文件读取、PCM数据解码、波形绘制和缩放参数处理。代码结构清晰,注释详细,可读性较好。异常处理也比较完善。但在信号处理准确性和代码质量方面还有一些改进空间,如优化变量命名,避免使用HTML实体等。

进阶难度评测结果

  • 得分:89.0 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

```python """ 实时音频波形可视化器 依赖安装命令: pip install PyAudio numpy scipy PyQt5 matplotlib 运行说明: - 启动程序后默认显示时域波形(Line模式)和频域频谱(Bar模式) - 快捷键: 't' 切换时域显示模式(Line Bar) 'f' 切换频域显示模式(Line Bar) 'p' 暂停/继续采集 'g' 增加增益(+6dB) 'r' 减少增益(-6dB) - 频域显示范围:0 ~ 20000 Hz - 频谱使用汉宁窗+Hann-EMA平滑 """ import sys import numpy as np from scipy.fft import fft, fftfreq from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QSizePolicy ) from PyQt5.QtCore import QTimer, QThread, pyqtSignal from PyQt5.QtGui import QPainter, QPen, QColor, QFont import pyaudio # ====================== # 音频采集线程(独立线程避免阻塞UI) # ====================== class AudioCaptureThread(QThread): """ 后台线程持续采集音频数据,通过信号发送给主线程处理。 采样率固定为44100Hz,帧大小为1024(23ms/帧)。 """ audio_data_signal = pyqtSignal(np.ndarray) def __init__(self, sample_rate=44100, chunk_size=1024, gain_db=0.0): super().__init__() self.sample_rate = sample_rate self.chunk_size = chunk_size self.gain_db = gain_db self.gain_linear = 10 ** (gain_db / 20.0) # dB转线性增益 self._running = True self._paused = False # 初始化PyAudio self.p = pyaudio.PyAudio() self.stream = self.p.open( format=pyaudio.paInt16, channels=1, rate=self.sample_rate, input=True, frames_per_buffer=self.chunk_size, start=False # 手动启动 ) def run(self): self.stream.start_stream() while self._running: if not self._paused: try: raw_data = self.stream.read(self.chunk_size, exception_on_overflow=False) # 将字节数据转为int16 numpy数组,并应用增益 samples = np.frombuffer(raw_data, dtype=np.int16).astype(np.float32) samples *= self.gain_linear # 归一化到[-1, 1](int16最大值为32767) samples = np.clip(samples, -32768, 32767) / 32767.0 self.audio_data_signal.emit(samples) except Exception as e: print(f"Audio read error: {e}") else: self.msleep(10) # 暂停时短暂休眠降低CPU占用 self.stream.stop_stream() self.stream.close() self.p.terminate() def pause(self): self._paused = True def resume(self): self._paused = False def set_gain_db(self, gain_db): self.gain_db = gain_db self.gain_linear = 10 ** (gain_db / 20.0)...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【GEMINI】这是一份非常优秀的实现方案。候选人不仅精通 Python 音频处理库(PyAudio, NumPy, SciPy),还展示了扎实的 GUI 开发功底。代码结构清晰,模块化程度高(将采集、时域绘制、频域绘制封装为独立类),注释详尽且准确地解释了信号处理的数学原理。使用 PyQt5 原生绘图(QPainter)代替 Matplotlib 动画极大提升了实时渲染的性能和视觉丝滑度。 【KIMI】该代码实现了实时音频波形可视化器的核心功能,包括独立线程采集、时域/频域双图显示、模式切换、EMA 平滑和暂停/继续控制。代码结构清晰,UI 交互体验良好。但在直流分量处理和音量增益调节方面还有待完善。总体上是一个优秀的实现。

困难难度评测结果

  • 得分:82.5 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

## 文件1: main.py ```python import sys import numpy as np from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QComboBox, QLabel, QFileDialog, QHBoxLayout, QSizePolicy from PyQt5.QtCore import QThread, pyqtSignal, QTimer, Qt from PyQt5.QtOpenGL import QGLWidget from OpenGL.GL import * from audio_engine import AudioEngine from signal_processing import SignalProcessing from rendering_engine import RenderingEngine from plugin_manager import PluginManager class VisualizerWidget(QGLWidget): """ OpenGL 渲染窗口,负责调用渲染引擎绘制波形、频谱和粒子。 """ def __init__(self, parent=None): super().__init__(parent) self.format().setSamples(4) # 抗锯齿 self.audio_engine = AudioEngine() self.signal_processing = SignalProcessing() self.rendering_engine = RenderingEngine() self.plugin_manager = PluginManager(self) self.time_offset = 0.0 # 时间轴偏移(秒) self.zoom_factor = 1.0 # 时间轴缩放因子 self.mouse_drag_start = None self.mode = "waveform" # "waveform", "spectrum", "particles" self.recording = False self.frames = [] def initializeGL(self): glClearColor(0.05, 0.05, 0.05, 1.0) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) self.rendering_engine.initialize() self.plugin_manager.initializeGL() def resizeGL(self, w, h): glViewport(0, 0, w, h) self.rendering_engine.resize(w, h) def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) audio_data = self.audio_engine.get_current_audio() if audio_data is not None: self.rendering_engine.render( audio_data, self.mode, self.time_offset, self.zoom_factor, self.signal_processing, self.plugin_manager ) self.plugin_manager.paintGL() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.mouse_drag_start = (event.x(), event.y()) def mouseMoveEvent(self, event): if self.mouse_drag_start is not None: dx = event.x() - self.mouse_drag_start[0] time_delta = dx / self.width() / self.zoom_factor self.time_offset -= time_delta self.mouse_drag_start = (event.x(), event.y()) self.update() def...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【KIMI】总体而言,该音频波形可视化器实现了大部分核心功能,性能和用户体验表现良好。在功能完整性、信号处理准确性、并发处理和代码质量等方面都表现不错,基本达到了专业级应用的要求。但仍有一些细节需要改进和完善,如节拍检测算法、异常处理、代码可扩展性等。综合来看,这是一个高质量的音频可视化项目。

相关链接

您可以通过以下链接查看更多相关内容:

加载中...