143 lines
4.5 KiB
Python
143 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
测试sounddevice音频播放功能
|
|
用于验证新的音频实现是否正常工作
|
|
"""
|
|
|
|
import numpy as np
|
|
import sounddevice as sd
|
|
import time
|
|
|
|
def test_sounddevice():
|
|
"""测试sounddevice音频播放"""
|
|
print("=== SoundDevice音频播放测试 ===")
|
|
|
|
# 1. 检查音频设备
|
|
print("\n1. 检查音频设备...")
|
|
try:
|
|
devices = sd.query_devices()
|
|
print(f"找到 {len(devices)} 个音频设备:")
|
|
for i, dev in enumerate(devices):
|
|
print(f" [{i}] {dev['name']} (输入: {dev['max_input_channels']}, 输出: {dev['max_output_channels']})")
|
|
|
|
# 查找默认输出设备
|
|
default_output = sd.default.device
|
|
print(f"默认输出设备: {default_output}")
|
|
except Exception as e:
|
|
print(f"音频设备检查失败: {e}")
|
|
return False
|
|
|
|
# 2. 测试生成和播放音频
|
|
print("\n2. 测试生成和播放音频...")
|
|
try:
|
|
# 生成1秒的440Hz正弦波
|
|
sample_rate = 24000
|
|
duration = 1.0
|
|
frequency = 440
|
|
|
|
t = np.linspace(0, duration, int(sample_rate * duration), False)
|
|
audio_data = np.sin(2 * np.pi * frequency * t) * 0.3 # 30%音量
|
|
|
|
# 转换为16-bit整数
|
|
audio_data_int16 = (audio_data * 32767).astype(np.int16)
|
|
|
|
print(f"生成音频数据: 采样率={sample_rate}Hz, 时长={duration}秒, 频率={frequency}Hz")
|
|
print(f"音频数据形状: {audio_data_int16.shape}, 数据类型: {audio_data_int16.dtype}")
|
|
|
|
# 播放音频
|
|
print("开始播放测试音频...")
|
|
sd.play(audio_data_int16, sample_rate)
|
|
sd.wait() # 等待播放完成
|
|
print("✓ 音频播放成功")
|
|
|
|
except Exception as e:
|
|
print(f"音频播放失败: {e}")
|
|
return False
|
|
|
|
# 3. 测试直接播放字节数据
|
|
print("\n3. 测试直接播放字节数据...")
|
|
try:
|
|
# 将numpy数组转换为字节数据
|
|
byte_data = audio_data_int16.tobytes()
|
|
print(f"字节数据长度: {len(byte_data)} 字节")
|
|
|
|
# 将字节数据转换回numpy数组
|
|
audio_array = np.frombuffer(byte_data, dtype=np.int16)
|
|
|
|
# 播放
|
|
print("开始播放字节数据...")
|
|
sd.play(audio_array, sample_rate)
|
|
sd.wait()
|
|
print("✓ 字节数据播放成功")
|
|
|
|
except Exception as e:
|
|
print(f"字节数据播放失败: {e}")
|
|
return False
|
|
|
|
# 4. 测试立体声
|
|
print("\n4. 测试立体声播放...")
|
|
try:
|
|
# 创建立体声数据
|
|
stereo_data = np.column_stack([audio_data_int16, audio_data_int16])
|
|
print(f"立体声数据形状: {stereo_data.shape}")
|
|
|
|
print("开始播放立体声音频...")
|
|
sd.play(stereo_data, sample_rate)
|
|
sd.wait()
|
|
print("✓ 立体声播放成功")
|
|
|
|
except Exception as e:
|
|
print(f"立体声播放失败: {e}")
|
|
return False
|
|
|
|
return True
|
|
|
|
def test_numpy_conversion():
|
|
"""测试numpy数组转换"""
|
|
print("\n5. 测试数据类型转换...")
|
|
|
|
# 模拟火山引擎返回的16bit PCM数据
|
|
test_data = b'\x00\x00\x7f\x7f\x80\x00\xff\xff' # 一些测试音频数据
|
|
|
|
try:
|
|
# 字节数据转numpy数组
|
|
audio_array = np.frombuffer(test_data, dtype=np.int16)
|
|
print(f"原始字节数据: {test_data}")
|
|
print(f"转换后numpy数组: {audio_array}")
|
|
print(f"数组形状: {audio_array.shape}, 数据类型: {audio_array.dtype}")
|
|
|
|
# 重塑为单声道
|
|
audio_reshaped = audio_array.reshape(-1, 1)
|
|
print(f"重塑后形状: {audio_reshaped.shape}")
|
|
|
|
# 转回字节数据
|
|
byte_data = audio_array.tobytes()
|
|
print(f"转回字节数据: {byte_data}")
|
|
|
|
print("✓ 数据类型转换测试成功")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"数据类型转换失败: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
print("SoundDevice音频播放功能测试")
|
|
print("=" * 50)
|
|
|
|
success = True
|
|
|
|
# 测试sounddevice
|
|
if not test_sounddevice():
|
|
success = False
|
|
|
|
# 测试数据转换
|
|
if not test_numpy_conversion():
|
|
success = False
|
|
|
|
print("\n" + "=" * 50)
|
|
if success:
|
|
print("✓ 所有SoundDevice测试通过")
|
|
print("树莓派应该可以正常播放音频了!")
|
|
else:
|
|
print("✗ 部分测试失败,需要进一步调试") |