scipy.rfft分析电脑音频时检测频率为预期值一半的问题咨询
问题原因
你遇到的频率减半、存在镜像峰的问题,核心原因是读取立体声音频流时直接按单声道序列做了解码处理:
- Pyaudio默认开启的音频流为双声道(立体声)格式,每个音频帧包含左、右两个通道的16位采样值
- 你调用
stream.read(int(self.sampleRate/10))拿到的缓冲区,对应sampleRate/10个立体声帧,用np.frombuffer(..., np.int16)解码后得到的数组长度是2*sampleRate/10,是实际单声道采样帧数的两倍 - 将两倍长度的数组传入rfft计算时,
rfftfreq用错误的序列长度计算频率轴,最终得到的频率值只有实际值的一半;而你观测到的12kHz镜像峰,刚好对应44100Hz采样率的奈奎斯特频率(22050Hz)减去原始10kHz信号的频率值,是序列拼接错误带来的典型混叠伪影。
修复方案
方案1:流读取后转单声道
如果你的流本身就是立体声配置,解码后提取单通道数据再做FFT即可,修改读取代码如下:
frames = np.frombuffer( self.stream.read(int(self.sampleRate/10)), np.int16) # 新增:提取左通道数据,也可替换为 frames[1::2] 取右通道,或左右通道平均 frames = frames[::2] xf, yf = audioUtils.getSpectrum(frames, self.sampleRate) self.plotWidget.plot(xf, yf)
方案2:直接开启单声道流
在初始化Pyaudio流时,将channels参数设置为1,只要你使用的分支支持单声道环回录制,读取的缓冲区就直接是单声道采样,无需额外处理。
验证方法
你可以打印解码后的len(frames)值确认问题:如果未做处理时长度是8820(对应44100Hz采样率下0.1秒的立体声数据),处理后变为4410,就说明问题根因确实是立体声未转单声道。
内容的提问来源于stack exchange,提问作者Cyrano Chatziantoniou
相关产品推荐
相关产品推荐

