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

Python处理WAV文件报错:ushort格式要求0<=数值<=0xffff求解答

解决WAV拼接时的ushort format requires 0 <= number <= 0xffff错误

问题背景

尝试将WAV文件分割为37个片段,经过HRTF卷积处理后重新拼接,最终播放时触发ushort format requires 0 <= number <= 0xffff错误。

实现代码

path = 'C:/Users/example/Documents/folder/'
Fs, xSom = wavfile.read('sample.wav')
xSom_ = xSom[:Fs*2]
#print(np.array_split(xSom_,37))
for i in range(37):
    hrtf100 = np.fromfile(path + 'beep' + str(i*10).zfill(3) + 'boop.dat', dtype='short')
    hrtf100.dtype
    hrtf100.shape
    hrtf100_L = hrtf100[0::2]
    hrtf100_R = hrtf100[1::2]
    hrtf100_R_F = hrtf100_R.astype(np.float64)
    hrtf100_L_F = hrtf100_L.astype(np.float64)
    hrtf100_R_F_N = hrtf100_R_F/np.abs(np.max(hrtf100_R_F))
    hrtf100_L_F_N = hrtf100_L_F/np.abs(np.max(hrtf100_L_F))
    xSom_split = np.array_split(xSom_,37)[i]
    xSom_split.dtype
    xSom_F = xSom_split.astype(np.float64)
    xSom_F.dtype
    xSom_F_N = xSom_F / np.abs(np.max(xSom_F))
    out_L = np.convolve(hrtf100_L_F_N, xSom_F_N)
    out_R = np.convolve(hrtf100_R_F_N, xSom_F_N)
    out_L = out_L / np.abs(np.max(out_L))*(2**15-1)
    out_R = out_R / np.abs(np.max(out_R))*(2**15-1)
    out = np.zeros((len(out_L),2))
    out[:,0] = out_L
    out[:,1] = out_R
    if i>0:
        full_signal = np.concatenate((full_signal,out))
    else:
        full_signal = out

display(Audio(data = full_signal.astype(np.int16), rate= Fs)) 

错误日志

~\AppData\Local\Temp\ipykernel_23744\379706904.py in <module>
----> 1 BinauralRotativo()

~\AppData\Local\Temp\ipykernel_23744\2326583148.py in BinauralRotativo()
     32             full_signal = out
     33 
---> 34     display(Audio(data = full_signal.astype(np.int16), rate= Fs))

c:\users\example\appdata\local\programs\python\python37\lib\site-packages\IPython\lib\display.py in __init__(self, data, filename, url, embed, rate, autoplay, normalize, element_id)
    115             if rate is None:
    116                 raise ValueError("rate must be specified when data is a numpy array or list of audio samples.")
---> 117             self.data = Audio._make_wav(data, rate, normalize)
    118 
    119     def reload(self):

c:\users\example\appdata\local\programs\python\python37\lib\site-packages\IPython\lib\display.py in _make_wav(data, rate, normalize)
    147         waveobj.setsampwidth(2)
    148         waveobj.setcomptype('NONE','NONE')
---> 149         waveobj.writeframes(scaled)
    150         val = fp.getvalue()
    151         waveobj.close()

c:\users\example\appdata\local\programs\python\python37\lib\wave.py in writeframes(self, data)
    436 
    437     def writeframes(self, data):
---> 438         self.writeframesraw(data)
    439         if self._datalength != self._datawritten:
    440             self._patchheader()

c:\users\example\appdata\local\programs\python\python37\lib\wave.py in writeframesraw(self, data)
    425         if not isinstance(data, (bytes, bytearray)):
    426             data = memoryview(data).cast('B')
---> 427         self._ensure_header_written(len(data))
    428         nframes = len(data) // (self._sampwidth * self._nchannels)
    429         if self._convert:

c:\users\example\appdata\local\programs\python\python37\lib\wave.py in _ensure_header_written(self, datasize)
    466             if not self._framerate:
    467                 raise Error('sampling rate not specified')
---> 468             self._write_header(datasize)
    469 
    470     def _write_header(self, initlength):

c:\users\example\appdata\local\programs\python\python37\lib\wave.py in _write_header(self, initlength)
    483             self._nchannels * self._framerate * self._sampwidth,
    484             self._nchannels * self._sampwidth,
---> 485             self._sampwidth * 8, b'data'))
    486         if self._form_length_pos is not None:
    487             self._data_length_pos = self._file.tell()

error: ushort format requires 0 <= number <= 0xffff 

错误原因

这个错误的核心是音频数据超出了int16类型的合法取值范围。int16的有效范围是-32768到32767,wave模块存储时会将有符号int16转换为无符号ushort(0到65535),一旦数据超出原范围,就会触发格式错误。

具体到代码中的问题:

  1. 逐段归一化的局限性:每个片段处理后单独归一化到int16范围,但拼接后的全局数据可能因浮点精度误差,出现略大于32767或略小于-32768的值。
  2. 极端值处理疏漏:如果某个片段的out_L/out_R全为0,np.abs(np.max(out_L))会导致除以0,产生NaN或无穷大值,转int16时直接触发错误。

修复方案

1. 全局归一化替代逐段归一化

去掉每个片段中的int16范围归一化,保留浮点状态,拼接完成后再做一次全局归一化,确保所有数据都在合法范围内。

2. 处理异常值

添加NaN和无穷大值的处理逻辑,避免无效数据进入后续步骤。

3. 优化分割逻辑(可选)

如果需要等长片段,建议用np.split(需总长度能被37整除)或手动计算索引,替代np.array_split的近似分割。

修复后的完整代码

path = 'C:/Users/example/Documents/folder/'
Fs, xSom = wavfile.read('sample.wav')
xSom_ = xSom[:Fs*2]
full_signal = []

for i in range(37):
    hrtf100 = np.fromfile(path + 'beep' + str(i*10).zfill(3) + 'boop.dat', dtype='short')
    hrtf100_L = hrtf100[0::2]
    hrtf100_R = hrtf100[1::2]
    hrtf100_R_F = hrtf100_R.astype(np.float64)
    hrtf100_L_F = hrtf100_L.astype(np.float64)
    
    # 处理HRTF归一化,避免除以0
    hrtf_max_R = np.abs(np.max(hrtf100_R_F))
    hrtf100_R_F_N = hrtf100_R_F / hrtf_max_R if hrtf_max_R > 0 else hrtf100_R_F
    hrtf_max_L = np.abs(np.max(hrtf100_L_F))
    hrtf100_L_F_N = hrtf100_L_F / hrtf_max_L if hrtf_max_L > 0 else hrtf100_L_F
    
    xSom_split = np.array_split(xSom_,37)[i]
    xSom_F = xSom_split.astype(np.float64)
    
    # 处理音频片段归一化,避免除以0
    x_max = np.abs(np.max(xSom_F))
    xSom_F_N = xSom_F / x_max if x_max > 0 else xSom_F
    
    out_L = np.convolve(hrtf100_L_F_N, xSom_F_N)
    out_R = np.convolve(hrtf100_R_F_N, xSom_F_N)
    
    # 暂不做int16范围归一化,保持浮点
    out = np.zeros((len(out_L),2))
    out[:,0] = out_L
    out[:,1] = out_R
    full_signal.append(out)

# 拼接所有片段
full_signal = np.concatenate(full_signal, axis=0)

# 处理NaN和无穷大值
full_signal = np.nan_to_num(full_signal, nan=0.0, posinf=32767, neginf=-32768)

# 全局归一化并严格限制范围
max_val = np.abs(full_signal).max()
if max_val > 0:
    full_signal = full_signal / max_val * (2**15 - 1)
full_signal = np.clip(full_signal, -32768, 32767)

display(Audio(data = full_signal.astype(np.int16), rate= Fs))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:10:30