You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python写入音频文件后读取出现失真问题求助

音频写入后读取失真的问题排查与解决

问题重现

以下是用于生成并写入音频的代码片段:

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
from scipy.signal import fftconvolve
from scipy import signal as sig
import soundfile as sf
import IPython

# 读取原始音频与房间脉冲响应
fs, signal = wavfile.read("whistle_01.wav")
fs2, rir_1_0 = wavfile.read("room_impulse.wav") # 采样率与fs一致
# 卷积生成带混响的音频
myaudio = sig.convolve(signal, rir_1_0)
plt.plot(myaudio)
IPython.display.Audio(myaudio, rate=fs)

写入前波形:
写入前波形

执行写入与读取操作:

sf.write('test.wav', myaudio, fs)
freq, mysig = wavfile.read("test.wav")
plt.plot(mysig)

写入后读取的失真波形:
写入后波形

问题:卷积生成的音频在IPython中播放正常,但写入文件后再次读取,波形完全失真。

原因分析

  1. 数据类型与幅值范围不匹配
    scipy.signal.convolve输出的是float64类型数据,而多数WAV音频文件采用16位PCM格式(int16类型,数值范围为[-32768, 32767])。直接写入float64数据时,soundfile.write会默认将其视为范围[-1, 1]的标准化音频,但如果卷积后的音频幅值远大于1,写入时会被强制截断到合法范围,导致读取后波形畸变。
  2. 读取工具的格式兼容性
    wavfile.read读取文件时,会根据文件头的格式标识解析数据。如果写入的是float格式的WAV,wavfile.read虽然能读取,但部分场景下会因类型转换逻辑导致波形显示异常。

修正方案

方案1:归一化后写入(推荐)

将卷积后的音频数据归一化到[-1, 1]范围,确保符合WAV文件的标准化格式:

# 归一化音频数据到[-1, 1]
myaudio_normalized = myaudio / np.max(np.abs(myaudio))
# 写入文件
sf.write('test.wav', myaudio_normalized, fs)
# 读取验证
freq, mysig = wavfile.read("test.wav")
plt.plot(mysig)

方案2:转换为int16格式写入(匹配原始音频)

如果原始音频是int16类型,直接将卷积数据缩放并转换为对应类型,保持与原始文件格式一致:

# 缩放数据到int16的范围并转换类型
myaudio_int16 = np.int16(myaudio / np.max(np.abs(myaudio)) * 32767)
# 使用wavfile写入,确保格式匹配
wavfile.write('test.wav', fs, myaudio_int16)
# 读取验证
freq, mysig = wavfile.read("test.wav")
plt.plot(mysig)

内容的提问来源于stack exchange,提问作者se7en

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:53:35