如何修改scipy.io.wavfile.read以读取11位深度ECG信号WAV文件?
解决Scipy读取11位深度WAV文件的问题
嘿,我完全懂你碰到的这个糟心问题——scipy.io.wavfile.read确实只支持标准的8/16/24/32位深度的WAV文件,碰到11位这种非标准格式直接就报错了。下面给你两种实用的解决思路,代码拿过去就能用:
方法一:用Python内置wave模块手动解析
这个方法更底层,能自己处理任意位深度的PCM数据,完全可控:
import wave import numpy as np def read_11bit_wav(file_path): with wave.open(file_path, 'rb') as wav_file: # 获取WAV文件基础信息 n_channels = wav_file.getnchannels() sample_rate = wav_file.getframerate() n_frames = wav_file.getnframes() # 读取原始字节数据 raw_data = wav_file.readframes(n_frames) # 处理11位采样:每11位对应一个采样值,需要按字节拆分重组比特流 total_samples = n_frames * n_channels total_bits = total_samples * 11 # 把字节转成连续的比特字符串 bit_stream = ''.join(f'{byte:08b}' for byte in raw_data) # 截取有效比特(末尾可能有补零,只取前total_bits位) bit_stream = bit_stream[:total_bits] # 拆分每个11位采样并转为整数 samples = [] for i in range(0, total_bits, 11): sample_bits = bit_stream[i:i+11] # 处理有符号PCM的符号位(如果是无符号格式,去掉这段逻辑即可) if sample_bits[0] == '1': # 负数:取反加1转十进制 sample = -((int(sample_bits[1:], 2) ^ 0x7FF) + 1) else: sample = int(sample_bits[1:], 2) samples.append(sample) # 转为numpy数组并按声道整理形状 samples_np = np.array(samples, dtype=np.int16).reshape(-1, n_channels) return sample_rate, samples_np # 使用示例 rate, data = read_11bit_wav('sig100.wav') print(f"采样率: {rate}") print(f"数据形状: {data.shape}")
小提示:
- 这里默认你的11位WAV是有符号PCM格式,如果是无符号的,直接删除符号位处理的代码段就行。
- 最终用
int16存储数据,因为11位采样的范围(-1024到1023)完全能被int16覆盖。
方法二:用librosa库读取(更简洁省心)
librosa对非标准WAV格式的兼容性比scipy好很多,它会自动处理位深度的问题:
import librosa # 读取文件,sr=None表示保留原采样率不重采样 data, rate = librosa.load('sig100.wav', sr=None) print(f"采样率: {rate}") print(f"数据形状: {data.shape}")
说明:
- librosa会自动把采样数据归一化到[-1, 1]的浮点型数组,如果需要原始整数格式,可以用
librosa.util.buf_to_int转换回去。 - 用之前需要先安装librosa:
pip install librosa
另外,其实不太推荐修改scipy.io.wavfile.read的源码来适配11位格式——要改的地方涉及位深度判断、数据解析逻辑等好几个部分,而且scipy每次更新都会覆盖你的修改,远不如上面两种方法靠谱。
内容的提问来源于stack exchange,提问作者Abyr
相关产品推荐
相关产品推荐

