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),一旦数据超出原范围,就会触发格式错误。
具体到代码中的问题:
- 逐段归一化的局限性:每个片段处理后单独归一化到int16范围,但拼接后的全局数据可能因浮点精度误差,出现略大于32767或略小于-32768的值。
- 极端值处理疏漏:如果某个片段的
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
相关产品推荐
相关产品推荐

