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中播放正常,但写入文件后再次读取,波形完全失真。
原因分析
- 数据类型与幅值范围不匹配
scipy.signal.convolve输出的是float64类型数据,而多数WAV音频文件采用16位PCM格式(int16类型,数值范围为[-32768, 32767])。直接写入float64数据时,soundfile.write会默认将其视为范围[-1, 1]的标准化音频,但如果卷积后的音频幅值远大于1,写入时会被强制截断到合法范围,导致读取后波形畸变。 - 读取工具的格式兼容性
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
相关产品推荐
相关产品推荐

